题目请戳这里
题目大意:给一张无向图,边权为正整数,代表两端点之间路上能承载的最大重量,给定一个起点和一个终点,问起点到终点最大载货量。
题目分析:此题方法很多。floyd比较好想。每条路都有最大承载重量,所以经过这条路的车重量不能超过这个数,所以要求起点到终点所以路径中既能保证通过所有路,又要保证运货量最大。点的数量不超过200,所以可以直接floyd,通过枚举任意2点之间所有路径,取最大值。那么此题的方程为:
weight[i][j] = max(weight[i][j],min(weight[i][k],weight[k][j]))。
其中min(weight[i][k],weight[k][j])是为了保证车能顺利从i到k,再从k到j,最后取最大值。
通过和这题的比较可以发现,floyd绝不是简单的3重循环,对里面的式子做些变形,floyd也可以灵活变通,达到比较好的效果。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 205; const int M = 20005; const int INF = 0x3f3f3f3f; int weight[N][N]; char city[N][33]; int m,n,num; char str[33]; int st,ed; int getid() { int i; for(i = 1;i < num;i ++) if(strcmp(str,city[i]) == 0) return i; return i; } void Floyd() { int i,j,k; for(k = 1;k <= n;k ++) for(i = 1;i <= n;i ++) for(j = 1;j <= n;j ++) weight[i][j] = max(weight[i][j],min(weight[i][k],weight[k][j])); } int main() { //freopen("data.in","r",stdin); int i,a,b; int cas = 0; while(scanf("%d%d",&n,&m),(n + m)) { num = 1; memset(weight,0,sizeof(weight)); for(i = 1;i <= m;i ++) { scanf("%s",str); a = getid(); if(a == num) strcpy(city[num],str),num++; scanf("%s",str); b = getid(); if(b == num) strcpy(city[num],str),num++; scanf("%d",&weight[a][b]); weight[b][a] = weight[a][b]; } scanf("%s",str); st = getid(); scanf("%s",str); ed = getid(); printf("Scenario #%d\n",++cas); Floyd(); printf("%d tons\n\n",weight[st][ed]); } return 0; } //288K 32MS