Heavy Transportation
题目大意: 一个城市有n个街道(1~n),每两个街道有些是相通的,可容纳一些物品流通,但是这个通路是有大小的,因此可流通的物品大小不一,现在要从街道1流通一些物品去街道n,问一次可以流通多大的物品。通俗的讲就是求1->n所有路径中最小距离最大的那段。
题目思路: 先用map记录任意两个街道的权值,如果不存在则为0。然后用dijkstra算法,dis数组现在作用是记录所有街道到开始点的路径中最短的距离(权值),也就是题目所要求的。
Dis数组改进: 第一步,遍历所有点,记录开始点到所有点的距离,用dis数组保存。此时dis存的就是所有街道到开始点的路径中最短的距离,第二步,找到未标记的到dis最大的一段dis[k](让流通的物品可最大),1>若k不为目的点:对他进行标记,并遍历剩下的点,如果存在有dis[j]<map[k][j]&&dis[j]<dis[k](存在一条k->j的路可以使出发点到j的最小距离大于当前记录的最小距离),那么就应该更新,dis[j]=map[k][j]<dis[k]?map[k][j]:dis[k];,再重复第二步。2>:若k等于目的点(k已经是所有点到出发点最小距离中最大的点了)则结束并输出结果。
AC代码参考:
#include<stdio.h>
#include<math.h>
#define N 1010
#define INF 0x7ffffff
struct Point{
int x;
int y;
};
int map[N][N],dis[N];
int vis[N];
int Max(int x,int y){
return x>y?x:y;
}
void init(int s,int e){
int i,j;
for(i=s;i<=e;i++)
for(j=s;j<=e;j++){
map[i][j]=0;
}
}
void Dijkstra(int s,int e,int n){
int i,j,k;
int tmp;
for(i=1;i<=n;i++){
dis[i]=map[s][i];
vis[i]=0;
}
vis[s]=1;
while(1){
tmp=-1;
for(i=1;i<=n;i++){
if(!vis[i]&&dis[i]>tmp)
tmp=dis[k=i];
}
if(k==e) break;
vis[k]=1;
for(i=1;i<=n;i++){
if(!vis[i]&&dis[i]<map[k][i]&&dis[k]>dis[i]){
dis[i]=map[k][i]<dis[k]?map[k][i]:dis[k];
}
}
}
printf("%d\n\n",dis[n]);
}
int main(){
int i,j,n,m,k=1;
int a,b;
int c;
int ca;
scanf("%d",&ca);
while(ca--){
scanf("%d%d",&n,&m);
init(1,n);
for(i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
map[a][b]=map[b][a]=Max(map[a][b],c);
}
printf("Scenario #%d:\n",k++);
Dijkstra(1,n,n);
}
return 0;
}