【HDU 2433】Travel (BFS+最短路径树)

来源:互联网 发布:mac os acl 编辑:程序博客网 时间:2024/06/14 15:58

传送门

    Travel
    题意:一张n点m条边的图,边权均为1。对于每一条边,求删除它之后所有点对之间的最短路径和。

I think

    由于边权均为1,则可用BFS对每个点i求最短路并用Sum[i]记所有点到i的最短距离和。枚举删除边j时,若该边存在于点i的最短路径树中,对i进行屏蔽边j及其反向边的BFS再次求最短路。

Code

#include<queue>#include<cstdio>#include<cstring>#define s second using namespace std;typedef pair<int,int>pii;const int sm = 10005;const int sn = 105;const int Inf = 0x3f3f3f3f;int tot,N,M,ret,ans; bool fl=0; int fm[sm],to[sm],hd[sn],nxt[sm],tag[sm];int d[sn],pre[sn][sn],Sum[sn];int T[sn],vis[sn];void Add(int u,int v) {    fm[++tot]=u,to[tot]=v,nxt[tot]=hd[u],hd[u]=tot;    fm[++tot]=v,to[tot]=u,nxt[tot]=hd[v],hd[v]=tot;}int Bfs(int x,int ind){    if(ind) memcpy(T,pre[x],sizeof(T));    int t,cnt=1,sum=0;     for(int i=1;i<=N;++i) vis[i]=0;    d[x]=0;vis[x]=1;    queue<int>Q; Q.push(x);    while(!Q.empty()) {        t=Q.front();Q.pop();        for(int i=hd[t];i;i=nxt[i])            if(!vis[to[i]]&&!tag[i]) {                pre[x][to[i]]=t;                vis[to[i]]=1; ++cnt;                d[to[i]]=d[t]+1;                Q.push(to[i]);            }        if(cnt==N) break;    }    if(cnt!=N) { fl=1; return 0; }    for(int i=1;i<=N;++i) sum+=d[i];    if(ind) memcpy(pre[x],T,sizeof(T));    return sum;}void Init(){    tot=ret=0,fl=0;    for(int i=1;i<=N;++i) hd[i]=0;}int main() {    while(scanf("%d%d",&N,&M)!=EOF) {        Init(); int t,q,u,v;        for(int i=1;i<=M;++i)             scanf("%d%d",&u,&v),Add(u,v);        for(int i=1;i<=N;++i) {            Sum[i]=Bfs(i,0);            ret+=Sum[i];            if(fl)break;         }        if(fl) {            for(int i=1;i<=M;++i) puts("INF");            continue;        }        for(int i=1;i<=M;++i) {            t=(i-1)<<1|1; fl=0; ans=ret;             for(int j=1;j<=N;++j)                if(pre[j][fm[t]]==to[t]||pre[j][to[t]]==fm[t]) {                    tag[t]=tag[t+1]=1;                    q=Bfs(j,1);                    tag[t]=tag[t+1]=0;                    if(fl) break;                    ans=ans-Sum[j]+q;                }            if(fl) puts("INF");            else printf("%d\n",ans);        }    }    return 0;}
原创粉丝点击