题意:给出边建立图 然后依次删除给出的边,求最短路,如无法连通 则返回INF
这里最短路 = 多源最短路和 即求出对于单源最短路 再for一个循环求出多源最短路 相加
用dijkstra 复杂度为V*(E+V),由于这里很特殊 每条路长度都是1 故可以使用bfs 最先搜到的节点一定是最短的
bfs 时间复杂度 E , 但如果每次拆路都对所有节点重新求最短路 复杂度则是 E*V*E 还多个case 可能不过
这里可以使用used[x][u][v] 来记录对于以x为源点的树 是否使用town[u][v] 这条路 若有,则更新sum[x], 若无 continue
即更新所有有用到被拆路的树。。
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
bool used[105][105][105];
int map[105][105];
bool visit[105];
int dis[105];
int sum[105];
struct Edge
{
int a;
int b;
}edge[3005];
int n,m;
const int inf = 1000000;
int bfs(int src,bool flag)
{
int num=0;
for(int i = 0;i<=n;i++)
{
visit[i] = false;
dis[i] = inf;
}
queue<int> q;
q.push(src);
dis[src] = 0;
visit[src] = true;
while(!q.empty())
{
int temp = q.front();
q.pop();
for(int i = 1;i<=n;i++)
{
if(!visit[i]&&map[temp][i]>0)
{
visit[i] = true;
dis[i] = dis[temp]+1;
if(flag)
used[src][i][temp] = used[src][temp][i] = true;
q.push(i);
}
}
}
for(int i = 1;i<=n;i++)
{
if(dis[i]==inf)
{
return -1;
}
num+=dis[i];
}
if(flag)
sum[src] = num;
return num;
}
int main()
{
int u,v,ans,alllen;
bool flag;
while(scanf("%d %d",&n,&m)!=EOF)
{
flag = true;
ans = alllen = 0;
memset(map,0,sizeof(map));
memset(sum,0,sizeof(sum));
memset(used,0,sizeof(used));
for(int i = 1;i<=m;i++)
{
scanf("%d %d",&u,&v);
map[u][v]++;
map[v][u]++;
edge[i].a = u;
edge[i].b = v;
}
for(int i = 1;i<=n;i++)
{
int temp = bfs(i,true);
if(temp==-1)
{
flag = false;
break;
}
else
alllen+=temp;
}
for(int i = 1;i<=m;i++)
{
if(!flag)
printf("INF\n");
else
{
ans = alllen;
u = edge[i].a;
v = edge[i].b;
map[u][v]--;
map[v][u]--;
if(map[u][v]>0)
{
printf("%d\n",ans);
}
else
{
for(int j = 1;j<=n;j++)
{
if(used[j][u][v])
{
int temp = bfs(j,false);
if(temp==-1)
{
ans = -1;
break;
}
else
ans = ans - sum[j] +temp;
}
}
if(ans==-1)
printf("INF\n");
else
printf("%d\n",ans);
}
map[u][v]++;
map[v][u]++;
}
}
}
return 0;
}