现在的位置: 首页 > 综合 > 正文

HDOJ2433-最短路径树

2013年12月07日 ⁄ 综合 ⁄ 共 1760字 ⁄ 字号 评论关闭
//1406ms险过。
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=110;
const int MM=3100;
struct node{
    int v,e;
    node() {}
    node(int _v,int _e): v(_v),e(_e) {}
};
struct Edge{
    int u,v;
}e[MM];

vector<node> adj[NN];
int n,m,tot,ans,sum[NN],d[NN][NN],tmp_dis[NN];
bool intree[NN][MM],tmp_in[MM],vis[NN];

int top,bn,index,dfn[NN],low[NN],stack[NN],belong[NN];
bool instack[NN];
void tarjan(int u,int fa) //判断桥边
{
    dfn[u]=low[u]=++index;
    stack[++top]=u;
    instack[u]=true;

    int v;
    for (int i=0; i<adj[u].size(); i++)
    {
        if (adj[u][i].e==fa) continue;
        v=adj[u][i].v;
        if (!dfn[v])
        {
            tarjan(v,adj[u][i].e);
            if (low[v]<low[u]) low[u]=low[v];
        }
        else if (instack[v] && dfn[v]<low[u])
            low[u]=dfn[v];
    }

    if (low[u]==dfn[u])
    {
        bn++;
        do
        {
            v=stack[top--];
            instack[v]=false;
            belong[v]=bn;
        }while (v!=u);
    }
}

void bfs(int S,int dis[],bool in[],int forbid=-1) //此题的边长均为1,用bfs求最短路即可
{
    int u,v,e,i;

    memset(vis,0,sizeof(vis));
    dis[S]=0; vis[S]=true;

    queue<int> q;
    q.push(S);

    while (!q.empty())
    {
        u=q.front();
        q.pop();
        for (i=0; i<adj[u].size(); i++)
        {
            v=adj[u][i].v;
            e=adj[u][i].e;
            if (vis[v] || e==forbid) continue;
            in[adj[u][i].e]=true;
            dis[v]=dis[u]+1;
            vis[v]=true;
            q.push(v);
        }
    }
}

void pre_do()
{
    int i,j;

    index=top=bn=0;
    for (i=1; i<=n; i++) if (!dfn[i]) tarjan(i,-1);

    tot=0;
    memset(intree,0,sizeof(intree));
    for (i=1; i<=n; i++)
    {
        bfs(i,d[i],intree[i]);
        sum[i]=0;
        for (j=1; j<=n; j++) sum[i]+=d[i][j];
        tot+=sum[i];
    }
}

int main()
{
    int i,j,k,u,v;

    while (~scanf("%d%d",&n,&m))
    {
        for (i=1; i<=n; i++)
        {
            adj[i].clear();
            dfn[i]=0;
        }
        for (i=1; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            e[i].u=u; e[i].v=v;
            adj[u].push_back(node(v,i));
            adj[v].push_back(node(u,i));
        }
        pre_do();
        for (i=1; i<=m; i++)
        {
            u=e[i].u; v=e[i].v;
            if (belong[u]!=belong[v]) { puts("INF"); continue; }//桥边特判

            ans=tot;
            for (j=1; j<=n; j++)
            {
                if (!intree[j][i]) continue;
                ans-=sum[j];
                bfs(j,tmp_dis,tmp_in,i);
                for (k=1; k<=n; k++) ans+=tmp_dis[k];
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

抱歉!评论已关闭.