Link
题意:给一个 点 边无向图(路长均为1)。
求删除第 条边之后,图中所有点对 最短路长度和。
无解输出"INF"。
暴力做法:枚举 ,对每个点跑最短路。因为边等长可以BFS,
以某个点为起点,到其它所有点的最短路合在一起就是一颗生成树。
那么对于这个点来说,删除最短路树里的边才有可能对最短路长度产生影响。
所以先对每个点
求一次最短路树,
。
然后枚举边
。枚举点
,如果
在以
为根的最短路树上,就删边,重新搞
的最短路树。
。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<ctime>
#include<queue>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define reg register int
#define add_edge(a,b) nxt[++tot]=head[a],head[a]=tot,to[tot]=b
int N,M,tot=0,ans=0,viscnt=0,total=0;
int head[105]={},nxt[6005]={},to[6005]={},sum[105]={};
bool vis[105]={};
bool fail=0;
bool ext[105][3005]={};
queue<pair<int,int> >Q;
void BFS(int root,int x,int ref)
{
Q.push(make_pair(0,x));
vis[x]=1; viscnt=1; ans=0;
while(!Q.empty())
{
pair<int,int>qf=Q.front(); Q.pop();
ans+=qf.first;
for(reg i=head[qf.second];i;i=nxt[i])
{
if((vis[to[i]])||((i+1>>1)==ref))continue;
if(!ref)ext[root][(i+1>>1)]=1; vis[to[i]]=1; ++viscnt;
Q.push(make_pair(qf.first+1,to[i]));
}
}
}
int main()
{
while(~scanf("%d%d",&N,&M))
{
total=tot=0;
memset(ext,0,sizeof(ext));
for(int i=1;i<=N;++i)head[i]=0;
for(reg u,v,i=1;i<=M;++i)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
for(reg i=1;i<=N;++i)
{
memset(vis,0,sizeof(vis));
BFS(i,i,0); sum[i]=ans; total+=sum[i];
}
for(reg delta=0,i=1;i<=M;++i)
{
fail=0;
delta=0;
for(int j=1;j<=N;++j)
{
if(ext[j][i])
{
memset(vis,0,sizeof(vis));
BFS(j,j,i);
if(viscnt!=N){fail=1;break;}
delta+=ans-sum[j];
}
}
if(fail){printf("INF\n");continue;}
printf("%d\n",total+delta);
}
}
return 0;
}