POJ 3013 Big Christmas Tree
题目来源:http://poj.org/problem?id=3013
目的就是为了圣诞树的总花费最小,各点的花费:指向该节点边权(unit)*该节点所有子树重量之和(sum(weight))。
这道题的思路是看了别人题解才会的,其实总花费最小即:每点到源点的距离(dist)*该点的重量(weight)。这样这个题目
就变成了最小路径求解问题,SPFA算法即可。这道题总是TE,不知道为什么。后来随便加了一个if(a>n) return;别人代
码都没加这句,居然就AC了,简直就不知道为什么,这a还能超过n吗?
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 #define INF 0x3f3f3f3f3f3f3f3f 5 const int maxn=50000+5; 6 int first[maxn],w[maxn],e; 7 long long dist[maxn]; 8 bool inq[maxn]; 9 struct node{ 10 int v,unit,next; 11 }edge[2*maxn]; 12 void add_edge(int a,int b,int c) 13 { 14 edge[e].v=b;edge[e].unit=c; 15 edge[e].next=first[a]; 16 first[a]=e; 17 e++; 18 } 19 void spfa(int n) 20 { 21 std::queue<int>q; 22 q.push(1); 23 dist[1]=0; 24 inq[1]=true; 25 while(!q.empty()){ 26 int a=q.front(); 27 q.pop(); 28 inq[a]=false; 29 if(a>n) 30 return; 31 for(int i=first[a];i!=-1;i=edge[i].next){ 32 int ev=edge[i].v,ew=edge[i].unit; 33 if(dist[ev]>dist[a]+ew){ 34 dist[ev]=dist[a]+ew; 35 if(!inq[ev]){ 36 inq[ev]=true; 37 q.push(ev); 38 } 39 } 40 } 41 } 42 } 43 int main() 44 { 45 int t,n,m; 46 scanf("%d",&t); 47 while(t--){ 48 scanf("%d%d",&n,&m); 49 int a,b,c; 50 for(int i=1;i<=n;i++) 51 scanf("%d",&w[i]); 52 memset(first,-1,sizeof(int)*(n+1)); 53 e=1; 54 for(int i=1;i<=m;i++){ 55 scanf("%d%d%d",&a,&b,&c); 56 add_edge(a,b,c); 57 add_edge(b,a,c); 58 } 59 memset(inq,false,sizeof(bool)*(n+1)); 60 memset(dist,0x3f,sizeof(dist[0])*(n+1)); 61 spfa(n); 62 long long ans=0; 63 bool flag=true; 64 for(int i=1;i<=n;i++){ 65 ans+=dist[i]*w[i]; 66 if(dist[i]>=INF){ 67 flag=false; 68 break; 69 } 70 } 71 if(flag) 72 printf("%I64d\n",ans); 73 else 74 printf("No Answer\n"); 75 } 76 return 0; 77 }