poj1797
本人一直比较愚钝,所以做题之时只有多花时间,此题是dijkstra变形,网上较多代码却少有解释为什么,我为何我一样的菜鸟来解释一下吧。
首先你要明白dijkstra之所以能用贪心的原因,不明者可以看dijkstra,bellman-ford,floyd分析比较 也就是dist[i]在证明中表示原点到i的最短路径,显然此题的dist表示原点到i的路径中最大载重量,为什么dist也可以表示?,当dist[i]被选中时不会改变了吗?它就是最大载重吗?
如s->t最大载重是10,s->i->t最大载重是20,可能是t在i之前被选中吗?答案是不可能,若s->i->t最大载重是20那么该路上所有边都>=20也就意味着i必然先于t被选择,那么就保证了贪心的正确性,所以此题可用dijkstra。
View Code
1 #include <stdio.h>
2 #include <string.h>
3 #define MAXN 1001
4 #define MIN(a,b) ((a)?((a)<(b)?(a):(b)):(b))
5 #define INF (1<<29)
6 struct node
7 {
8 int d,w;
9 node* next;
10 };
11 node *head[MAXN],edge[MAXN*MAXN],*p;
12 bool v[MAXN];
13 int n,m,max[MAXN];
14 void dij()
15 {
16 for(int i=1;i<=n;max[i++]=0);
17 int t=1,f=0;
18 while(f!=-1)
19 {
20 f=-1;
21 for(int i=1;i<=n;++i)
22 if(!v[i]&&f<max[i])
23 f=max[i],t=i;
24 v[t]=true;
25 for(p=head[t];p;p=p->next)
26 if(!v[p->d]&&max[p->d]<MIN(max[t],p->w))
27 max[p->d]=MIN(max[t],p->w);
28 }
29 }
30 int main()
31 {
32 int num;
33 scanf("%d",&num);
34 for(int k=1;k<=num;++k)
35 {
36 p=edge;
37 memset(head,NULL,sizeof(head));
38 memset(v,false,sizeof(v));
39 scanf("%d %d",&n,&m);
40 for(int i=0,a,b,c;i<m;++i)
41 {
42 scanf("%d %d %d",&a,&b,&c);
43 p->d=b;
44 p->w=c;
45 p->next=head[a];
46 head[a]=p++;
47 p->d=a;
48 p->w=c;
49 p->next=head[b];
50 head[b]=p++;
51 }
52 dij();
53 printf("Scenario #%d:\n%d\n",k,max[n]);
54 printf("\n");
55 }
56 return 0;
57 }