最短路变形 poj3013
题目:http://poj.org/problem?id=3013
题意:给出n个点,m个边。给出每个点的权值,每个边的权值。求建立一棵树,root=1,求这棵树的最小费用,费用=树上每条边*子树中各顶点的权值。
思路:root的权值是没用的,而其余节点是必须用的,每条边*子树中各定点的权值=各个点*点到根的最短路,于是转化成了root到各个点的最短路。
610ms~
View Code
1 #include <queue> 2 #include <stdio.h> 3 #include <iostream> 4 using namespace std; 5 const long long INF=10000000000; 6 const int M=50005; 7 int n,m,edgeNum; 8 long long dis[M]; 9 int head[M]; 10 int visit[M]; 11 int weight[M]; 12 struct Edge{ 13 int w; 14 int to; 15 int next; 16 }edge[M*2]; 17 struct Node{ 18 int u; 19 int dis; 20 bool operator < (const Node &a) const{ 21 return dis>a.dis; 22 } 23 }; 24 void init(){ 25 int i; 26 edgeNum=0; 27 for(i=0;i<M;i++){ 28 visit[i]=0; 29 head[i]=-1; 30 dis[i]=INF; 31 } 32 } 33 void addEdge(int a,int b,int c){ 34 edge[edgeNum].w=c; 35 edge[edgeNum].to=b; 36 edge[edgeNum].next=head[a]; 37 head[a]=edgeNum++; 38 } 39 void Dij(int u){ 40 int i,v; 41 Node temp,now; 42 priority_queue<Node> q; 43 temp.dis=0; 44 temp.u=u; 45 dis[u]=0; 46 q.push(temp); 47 while(!q.empty()){ 48 temp=q.top(); 49 q.pop(); 50 if(visit[temp.u]) continue; 51 visit[temp.u]=1; 52 for(i=head[temp.u];i!=-1;i=edge[i].next){ 53 v=edge[i].to; 54 if(!visit[v]&&dis[v]>dis[temp.u]+edge[i].w){ 55 dis[v]=dis[temp.u]+edge[i].w; 56 now.dis=dis[v]; 57 now.u=v; 58 q.push(now); 59 } 60 } 61 } 62 return ; 63 } 64 int main(){ 65 int T,a,b,c,i; 66 scanf("%d",&T); 67 while(T--){ 68 scanf("%d%d",&n,&m); 69 init(); 70 for(i=0;i<n;i++) 71 scanf("%d",&weight[i]); 72 for(i=0;i<m;i++){ 73 scanf("%d%d%d",&a,&b,&c); 74 a--;b--; 75 addEdge(a,b,c); 76 addEdge(b,a,c); 77 } 78 Dij(0); 79 long long res=0; 80 for(i=0;i<n;i++){ 81 if(dis[i]==INF) break; 82 res+=dis[i]*weight[i]; 83 } 84 if(i==n) printf("%lld\n",res); 85 else puts("No Answer"); 86 } 87 return 0; 88 }
注意:long long