HDU 3072 (强连通分量)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3072

题目大意:为一个有向连通图加边。使得整个图全连通,有重边出现。

解题思路

先用Tarjan把强连通分量缩点。

由于整个图肯定是连通的,所以枚举每一条边,记录到非0这个点所在连通分量的最小cost。

一共需要累加cnt-1个连通分量的cost。

在Tarjan过程中的重边,可以用链式前向星结构解决。(vector邻接表会算错)

在枚举每条边的cost中,用cost[i]记录i这个连通分量的最小cost。

最后不要算上cost[scc[0]],因为0点所在的连通分量是免费的。

#include "cstdio"

#include "algorithm"

#include "stack"

#include "cstring"

using namespace std;

#define maxn 50005

#define LL long long

int head[maxn],tot,pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,cnt,cost[maxn];

stack<int> S;

struct Edge

{

    int to,next,c;

}e[100005];

void addedge(int u,int v,int c)

{

    e[tot].to=v;

    e[tot].next=head[u];

    e[tot].c=c;

    head[u]=tot++;

}

void tarjan(int u)

{

    pre[u]=lowlink[u]=++dfs_clock;

    S.push(u);

    for(int i=head[u];i!=-1;i=e[i].next)

    {

        int v=e[i].to;

        if(!pre[v])

        {

            tarjan(v);

            lowlink[u]=min(lowlink[u],lowlink[v]);

        }

        else if (!sccno[v]) lowlink[u]=min(lowlink[u],lowlink[v]);

    }

    if(lowlink[u]==pre[u])

    {

        cnt++;

        while(1)

        {

            int x=S.top();S.pop();

            sccno[x]=cnt;

            if(x==u) break;

        }

    }

}

int main()

{

    //freopen("in.txt","r",stdin);

    int n,m,u,v,c;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        memset(head,-1,sizeof(head));

        memset(pre,0,sizeof(pre));

        memset(lowlink,0,sizeof(lowlink));

        memset(sccno,0,sizeof(sccno));

        memset(cost,0x3f3f,sizeof(cost));

        tot=dfs_clock=cnt=0;

        for(int i=0;i<m;i++)

        {

            scanf("%d%d%d",&u,&v,&c);

            addedge(u,v,c);

        }

        for(int i=0;i<n;i++)

          if(!pre[i]) tarjan(i);

        LL sum=0;

        for(int i=0;i<n;i++)

            for(int j=head[i];j!=-1;j=e[j].next)

                if(sccno[i]!=sccno[e[j].to]) cost[sccno[e[j].to]]=min(cost[sccno[e[j].to]],e[j].c);

        for(int i=1;i<=cnt;i++)

            if(i!=sccno[0])

                sum+=cost[i];

        printf("%I64d\n",sum);

    }

}

 

你可能感兴趣的:(HDU)