Heavy Transportation POJ - 1797
考察:最小生成树或最短路
这类题型感觉终于搞懂了一点...蒟蒻落泪
这里还有道和本题差不多的题GO
思路:
我们要让最小边权最大,也就是我们尽量走权大的边.spfa更新dist数组时,要赋值大值.但同时我们也需要让这条路径边权最小,也就是这条语句:
dist[i]<min(g[t][i],dist[t])
min保证是此前路径的最小边.<保证是到达此点的最小边权尽量大.
此外注意一下初始化:dist[i]除了1外全部为0,dist[1]需要赋值0x3f3f3f3f,否则更新不了队列
1 #include <iostream> 2 #include <queue> 3 #include <cstring> 4 using namespace std; 5 const int N = 1010; 6 int g[N][N],n,m,dist[N]; 7 bool st[N]; 8 void spfa() 9 { 10 queue<int> q; 11 q.push(1); 12 st[1] = 1; 13 for(int i=1;i<=n;i++) dist[i] = 0; 14 dist[1] = 0x3f3f3f3f; 15 while(q.size()) 16 { 17 int t = q.front(); 18 st[t] = 0; 19 q.pop(); 20 for(int i=1;i<=n;i++) 21 { 22 if(dist[i]<min(g[t][i],dist[t])) 23 { 24 dist[i] = min(g[t][i],dist[t]); 25 if(!st[i]) q.push(i),st[i] = 1; 26 } 27 } 28 } 29 } 30 int main() 31 { 32 int T,kcase = 0; 33 scanf("%d",&T); 34 while(T--) 35 { 36 fill(st,st+N,0); 37 printf("Scenario #%d:\n",++kcase); 38 scanf("%d%d",&n,&m); 39 memset(g,0,sizeof g); 40 while(m--) 41 { 42 int x,y,z; 43 scanf("%d%d%d",&x,&y,&z); 44 g[x][y] = g[y][x] = z; 45 } 46 spfa(); 47 printf("%d\n\n",dist[n]); 48 } 49 return 0; 50 }
最小生成树的思路:
边要按权大的排序.当n与1在一个集合里,就可以跳出
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 const int N = 1010; 5 struct Edge{ 6 int x,y,w; 7 bool operator<(Edge t){ 8 return this->w<t.w; 9 } 10 }edge[N*N>>1]; 11 int n,m,p[N]; 12 int findf(int x) 13 { 14 if(x!=p[x]) p[x] = findf(p[x]); 15 return p[x]; 16 } 17 void inits() 18 { 19 for(int i=1;i<=n;i++) p[i] = i; 20 } 21 int main() 22 { 23 // freopen("in.txt","r",stdin); 24 int T; 25 scanf("%d",&T); 26 for(int i=1;i<=T;i++) 27 { 28 printf("Scenario #%d:\n",i); 29 scanf("%d%d",&n,&m); 30 inits(); 31 for(int j=1;j<=m;j++) 32 { 33 int x,y,w; scanf("%d%d%d",&edge[j].x,&edge[j].y,&edge[j].w); 34 } 35 sort(edge+1,edge+m+1); 36 for(int j=m;j>0;j--) 37 { 38 int px = findf(edge[j].x),py = findf(edge[j].y); 39 if(px!=py) 40 { 41 p[px] = py; 42 if(findf(1)==findf(n)) { printf("%d\n\n",edge[j].w); break;} 43 } 44 } 45 } 46 return 0; 47 }