链接:点击打开链接
题意:给出一个n个点m条边的无向图,问删除每一条边后每两个点最短路的和
代码:
#include <set>
#include <map>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m;
int x[3005],y[3005];
int d[105],ss[105],vis[105];
int s[105][105],fa[105][105],op[105][105];
int bfs(int S){
int i,u,sum;
memset(d,INF,sizeof(d));
memset(vis,0,sizeof(vis));
d[S]=0,vis[S]=1;
queue<int> qu;
qu.push(S);
while(qu.size()){ //因为边长是1,直接bfs
u=qu.front();
qu.pop();
for(i=1;i<=n;i++){
if(vis[i]==0&&op[u][i]!=0){
d[i]=d[u]+1;
vis[i]=1;
fa[S][i]=u; //fa[i][j]表示以i为根,j的父节点
qu.push(i);
}
}
}
sum=0;
for(i=1;i<=n;i++){;
if(d[i]>=INF)
return -1;
sum+=d[i];
}
return sum;
}
int main(){ //将每个节点作为根节点,向其他点
int i,j,ans,tmp,sig; //做最短路,从而形成了n颗树,树就
while(scanf("%d%d",&n,&m)!=EOF){ //叫做最短路树,所以只有修改最短路
memset(op,0,sizeof(op)); //上的边才会改变最短路的值,一共n棵
memset(s,INF,sizeof(s)); //树,每棵树n-1条边,因此复杂度为O(n*n*m)
for(i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
s[x[i]][y[i]]=s[y[i]][x[i]]=1;
op[x[i]][y[i]]++;
op[y[i]][x[i]]++;
}
sig=0;
for(i=1;i<=n;i++){
ss[i]=bfs(i);
if(ss[i]==-1)
sig=1;
}
for(i=1;i<=m;i++){
ans=0;
if(sig){ //本身就不连通的图,之后也不会连通
puts("INF");
continue;
}
op[x[i]][y[i]]--; //记录哪条边被删除
op[y[i]][x[i]]--;
for(j=1;j<=n;j++){
if(fa[j][x[i]]!=y[i]&&fa[j][y[i]]!=x[i])
ans+=ss[j];
else{
tmp=bfs(j);
if(tmp==-1){
ans=-1;
break;
}
else
ans+=tmp;
}
}
op[x[i]][y[i]]++;
op[y[i]][x[i]]++;
if(ans==-1)
puts("INF");
else
printf("%d\n",ans);
}
}
return 0;
}