[HDU2433] [2008成都区域赛] Travel [最短路树]

Link
题意:给一个 n n m m 边无向图(路长均为1)。
求删除第 i [ 1 , n ] i\in[1,n] 条边之后,图中所有点对 ( x , y ) (x,y) 最短路长度和。
无解输出"INF"。
N 1 0 2 , M 3 1 0 3 N\le10^2,M\le3*10^3

暴力做法:枚举 i i ,对每个点跑最短路。因为边等长可以BFS, Θ ( M 2 N ) \Theta(M^2N)

以某个点为起点,到其它所有点的最短路合在一起就是一颗生成树。
那么对于这个点来说,删除最短路树里的边才有可能对最短路长度产生影响。

所以先对每个点 B F S BFS 求一次最短路树, Θ ( N 2 ) \Theta(N^2)
然后枚举边 j j 。枚举点 i i ,如果 j j 在以 i i 为根的最短路树上,就删边,重新搞 i i 的最短路树。
Θ ( M N 2 ) \Theta(MN^2)

#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;
}

猜你喜欢

转载自blog.csdn.net/Estia_/article/details/83065531