【hdu】2433 Travel【最短路删边】

来源:互联网 发布:volt模板引擎 php 编辑:程序博客网 时间:2024/05/16 05:37
题意:

给出一个n节点m条边的图,设这个图所有点之间最短路之和为sum,然后输出删除每一条边之后的sum值,图不联通输出inf

题解:

第一次计算所有图之间最短路之和的时候

在spfa算法里面记录used[i][j][k]代表以i节点为起点进行spfa操作的时候最短路中经过路径j,k

然后在之后进行删边操作的时候 注意重边

每次都把包含有该条边的也即used[i][j][k]=1的i重新进行一次删边后的spfa就能得出答案

#include<queue>  #include<cstdio>  #include<cstring>  using namespace std;  const int N=3005,M=105;  struct node  {      int a,b;  }edge[N];  int n,m,ans,tmp,town[M][M],sum[M],vis[M],dist[M],a,b;  bool used[M][M][M];  int spfa(int src,bool mark)  {      queue<int>q;      memset(vis,0,sizeof(vis));      memset(dist,0,sizeof(dist));      q.push(src);      vis[src]=1;      while(!q.empty()){          int u=q.front();          q.pop();          for(int i=1;i<=n;i++){              if(!vis[i]&&(town[u][i]>0||town[i][u]>0)){                  vis[i]=1;                  if(mark==0){used[src][i][u]=1;used[src][u][i]=1;}//记录以src为起点的时候的最短路有没有用到某条边                  dist[i]+=dist[u]+1;                  q.push(i);              }          }      }      int tot=0;      for(int i=1;i<=n;i++){          if(!dist[i]&&i!=src)return -1;          tot+=dist[i];      }      return tot;  }  int main()  {      while(scanf("%d%d",&n,&m)!=EOF){          ans=0;          memset(town,0,sizeof(town));          memset(sum,0,sizeof(sum));          memset(used,0,sizeof(used));          for(int i=1;i<=m;i++){              scanf("%d%d",&a,&b);              edge[i].a=a;edge[i].b=b;              town[a][b]++;town[b][a]++;          }          for(int i=1;i<=n;i++){              sum[i]=spfa(i,0);              if(sum[i]==-1){ans=-1;break;}              else ans+=sum[i];          }          for(int i=1;i<=m;i++){//删边过程              tmp=ans;              town[edge[i].a][edge[i].b]--;              town[edge[i].b][edge[i].a]--;              if(ans==-1)printf("INF\n");              else if(town[edge[i].a][edge[i].b]) printf("%d\n",ans);              else{//删边之后重新计算一次以该点为起点的最短路径 有用到这条边的顶点都要重新计算一次                  bool flag=0;                  for(int j=1;j<=n;j++)                  if(used[j][edge[i].a][edge[i].b]==1){                      tmp-=sum[j];                      int now=spfa(j,1);                      if(now==-1)                      {flag=1;break;}                      tmp+=now;                  }                  if(flag) printf("INF\n");                  else printf("%d\n",tmp);              }              town[edge[i].a][edge[i].b]++;              town[edge[i].b][edge[i].a]++;          }      }      return 0;  }  


0 0
原创粉丝点击