POJ 3013 Big Christmas Tree
TEST<22> 10-23
解题思路
就是 求最短路
然后 求 各个分支到根节点*边价值求和
AC 代码如下
/* spfa
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
int head[1000000];
struct map{//记录数组
int to;
int next;
int val;
}p[1000000];
int val[500000],vis[500000];//价值数组,标记数组
long long dis[500000];//累计权重数组
int n,m,ant;
int add(int x,int y,int w){ //添加数据函数
p[ant].to=y;
p[ant].val=w;
p[ant].next=head[x];
printf("ant:%d , to= %d, val = %d ",ant,p[ant].to,p[ant].val);
cout<<"head["<<x<<"]:"<<head[x]<<endl;
head[x]=ant++;//ant 作为点的唯一性 标志
return 0;
}
int spfa(int number){//最短路 spfa算法
memset(vis,0,sizeof(vis));//标记数组重置,也可以放到t 每组中 组头
for(int i=0;i<=n;i++)//重置为最大值
dis[i]=9999999999;
dis[number]=0; //初始点没有 儿子,0
vis[number]=1;//标记访问过
queue<int> s;
s.push(number);
while(!s.empty()){
int u=s.front();
s.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=p[i].next){ //扫描路径 , 进行松弛操作
int v=p[i].to;
int w=p[i].val;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
vis[v]=1;
s.push(v);
}
}
}
}
int flag=0;
long long sum=0;
for(int i=1; i<=n;i++){
if(dis[i]==9999999999){
flag=1;
break;
}
else
sum+=dis[i]*val[i];
}
if(flag)
printf("No Answer\n");
else
printf("%lld\n",sum);
return 0;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
ant=0;
//每组必须重置 这是 路径指向 函数数组
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<=m;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);//双向加入,可能存在 x-y-z最大
add(y,x,w);//双向加入 y-x-z
}
for(int i=0;i<=ant;i++)
printf("ant=%d :to=%d, next=%d, val=%d\n", i,p[i].to,p[i].next,p[i].val);
for(int i=0;i<=ant;i++)
cout<<i<<": "<<head[i]<<endl;
spfa(1);//从1开始 是否存在 可替换(缩小)操作
}
return 0;
}