zoukankan      html  css  js  c++  java
  • 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
    ",sum);
        }
    }
  • 相关阅读:
    hdu 6440 Dream(费马小定理+构造)
    [POJ3107]Godfather
    [POJ2488]A Knight's Journey
    [POJ3009]Curling 2.0
    [BZOJ1040][CODEVS1423][ZJOI2008]骑士
    [BZOJ1103] [POI2007]大都市meg
    BZOJ1827 [Usaco2010 Mar]gather 奶牛大集会
    [codevs1286]郁闷的出纳员
    [codevs3044]矩形面积求并
    BZOJ4563[Haoi2016]放棋子
  • 原文地址:https://www.cnblogs.com/neopenx/p/4500071.html
Copyright © 2011-2022 走看看