HDU-2433 Travel(最短路[Dijkstra])

来源:互联网 发布:电力监控软件 编辑:程序博客网 时间:2024/04/29 18:21

Travel

Time Limit: 10000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
      One day, Tom traveled to a country named BGM. BGM is a small country, but there are N (N <= 100) towns in it. Each town products one kind of food, the food will be transported to all the towns. In addition, the trucks will always take the shortest way. There are M (M <= 3000) two-way roads connecting the towns, and the length of the road is 1.
      Let SUM be the total distance of the shortest paths between all pairs of the towns. Please write a program to calculate the new SUM after one of the M roads is destroyed.

 

Input
      The input contains several test cases.
      The first line contains two positive integers N, M. The following M lines each contains two integers u, v, meaning there is a two-way road between town u and v. The roads are numbered from 1 to M according to the order of the input.
      The input will be terminated by EOF.

 

Output
      Output M lines, the i-th line is the new SUM after the i-th road is destroyed. If the towns are not connected after the i-th road is destroyed, please output “INF” in the i-th line. 
 

Sample Input
5 45 11 33 25 42 21 21 2
 

Sample Output
INFINFINFINF22


题目大意:多组输入,每组第一行读入定点数n和边数m,接下来m行是边。输出1~m条边分别摧毁后任意两点(分起点终点)的最短距离和,如果存在两点不连通,则INF


由于边数多,如果每次都计算任意两点的距离会超时。

看到大神的思路后,注意到每次只删除一条边,如果这条边在某两点(u,v)的最短路径中,则u,v两点的最短路长度会变,其他不变

但是太懒了,不想记录路径,又看到很多人直接只算(u,v)的最短路,然后减去原来u,v的最短路*2,加上最新的最短路*2就是答案,但这样的代码居然能AC,数据真是好水

例如这组数据就会挂很多人

4 4 1 22 33 4 2 4答案:INF201820


按照正确思路写出来,TLE,可能是太渣了,而且每对顶点都跑一边最短路径

又看到大神的另一种思路:used[x][u][v] 来记录对于以x为源点的最短路径树,是否使用w[u][v] 这条路,如果使用则重新计算一遍最短路,这样就能得到正确结果



#include <cstdio>#include <cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=105;int w[MAXN][MAXN],dis[MAXN][MAXN],dist[MAXN],num[MAXN][MAXN],sta[3005],des[3005];int n,m,s,e,u,tmp,sum,ans;bool vis[MAXN],used[MAXN][MAXN][MAXN];void Dijkstra() {    int i,j;    for(i=1;i<=n;++i) {        tmp=INF,e=0;        for(j=1;j<=n;++j)            if(!vis[j]&&dist[j]<tmp)                tmp=dist[u=j];        if(tmp==INF)            return ;        vis[u]=true;        for(j=1;j<=n;++j)            if(!vis[j]&&(tmp=dist[u]+w[u][j])<dist[j])                dist[j]=tmp;    }}void DijkstraInit() {    int i,j;    for(i=1;i<=n;++i) {        tmp=INF;        for(j=1;j<=n;++j)            if(!vis[j]&&dis[s][j]<tmp)                tmp=dis[s][u=j];        if(tmp==INF)            return ;        vis[u]=true;        for(j=1;j<=n;++j)            if(!vis[j]&&(tmp=dis[s][u]+w[u][j])<dis[s][j]) {                dis[s][j]=tmp;                used[s][u][j]=used[s][j][u]=true;            }    }}void Judge(int i) {    int j,k;    for(j=1;j<=n;++j) {        if(used[j][sta[i]][des[i]]) {            memset(vis,false,sizeof(vis));            memset(dist,0x3f,sizeof(dist));            dist[j]=0;            Dijkstra();            for(k=1;k<=n;++k)                if(dist[k]==INF) {                    ans=INF;                    return ;                }                else                    ans+=(dist[k]-dis[j][k])<<1;        }    }}int main() {    int i,j;    while(scanf("%d%d",&n,&m)==2) {        memset(w,0x3f,sizeof(w));        memset(dis,0x3f,sizeof(dis));//刚开始忘了初始化dis,结果差不多能跑到最后一组数据,一直以为是算法写错了。。。        memset(num,0,sizeof(num));        memset(used,false,sizeof(used));        for(i=0;i<m;++i) {            scanf("%d%d",&s,&e);            dis[sta[i]=s][des[i]=e]=dis[e][s]=w[s][e]=w[e][s]=1;            ++num[s][e],++num[e][s];//记录边出现的次数            used[s][s][e]=true;//由于dis[s][e]已经初始化,且权值为1,所以(s,e)一定会出现在以s为源点的最短路径树上        }        sum=0;        for(i=1;i<=n;++i) {            s=i,dis[i][i]=0;            memset(vis,false,sizeof(vis));            DijkstraInit();            for(j=1;j<i;++j)                sum+=(dis[i][j]<<1);//根据题意得图是连通的        }        for(i=0;i<m;++i) {            if(num[sta[i]][des[i]]>1)//特判,如果该边出现的次数>1就直接输出结果                printf("%d\n",sum);            else {                w[sta[i]][des[i]]=w[des[i]][sta[i]]=INF;                ans=sum;                Judge(i);                if(ans!=INF)                    printf("%d\n",ans);                else                    printf("INF\n");                w[sta[i]][des[i]]=w[des[i]][sta[i]]=1;            }        }    }    return 0;}




0 0
原创粉丝点击