• hdu 3072 有向图缩点成最小树形图计算最小权


    题意,从0点出发,遍历所有点,遍历边时候要付出代价,在一个SCC中的边不要付费。求最小费用。

    有向图缩点(无需建立新图,,n《=50000,建则超时),遍历边,若不在一个SCC中,用一个数组更新记录最小到达该连通分量的最小边权即可。。。边聊天,边1A,哈哈。。。

    #include<iostream>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int maxv=50005,maxe=100005;
    int nume=0;int head[maxv];int e[maxe][3];
    void inline adde(int i,int j,int c)
    {
        e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
        e[nume++][2]=c;
    }
    int dfn[maxv];int low[maxv];int vis[maxv];int ins[maxv]; stack<int>sta;
    int scc[maxv];int numb=0;int times=0;
    int n,m;
    void tarjan(int u)
    {
        dfn[u]=low[u]=times++;
        ins[u]=1;
        sta.push(u);
        for(int i=head[u];i!=-1;i=e[i][1])
        {
            int v=e[i][0];
            if(!vis[v])
            {
                vis[v]=1;
                tarjan(v);
                if(low[v]<low[u])low[u]=low[v];
            }
            else if(ins[v]&&dfn[v]<low[u])
            {
                low[u]=dfn[v];
            }
        }
        if(low[u]==dfn[u])
        {
            numb++;
            int cur;
           do
            {
                cur=sta.top();
                sta.pop();
                ins[cur]=0;
                scc[cur]=numb;
            }while(cur!=u);
        }
    }
    int mincost_to_v[maxv];    //记录
    void solve()
    {
         vis[0]=1;
         tarjan(0);
        for(int i=0;i<n;i++)
          for(int j=head[i];j!=-1;j=e[j][1])
          {
              int v=e[j][0];
              if(scc[i]!=scc[v])
            {
                if(e[j][2]<mincost_to_v[scc[v]])
                 {
                     mincost_to_v[scc[v]]=e[j][2];
                 }
            }
          }
        int sums=0;
        for(int i=1;i<=numb;i++)
            {
                if(mincost_to_v[i]!=inf)    //起点
                 sums+=mincost_to_v[i];
            }
       printf("%d
    ",sums);
    }
    void read_build()
    {
        int aa,bb,cc;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&aa,&bb,&cc);
            adde(aa,bb,cc);
        }
    }
    void init()
    {
        numb=times=nume=0;
        for(int i=0;i<maxv;i++)
          {
              head[i]=-1;
              ins[i]=dfn[i]=low[i]=scc[i]=vis[i]=0;
              mincost_to_v[i]=inf;
          }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            read_build();
            solve();
        }
        return 0;
    }
    


  • 相关阅读:
    栈溢出笔记1.3 准备Shellcode
    聊聊手游的那些惊喜与惊吓
    GIS+=地理信息+容器技术(4)——Docker执行
    与AQS有关的并发类
    HDU 2102 A计划
    生产系统ELK日志采集系统
    datagrip离线安装驱动jar
    oracle无效索引重建
    18年总结及19年展望
    shell符号解释
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925692.html
Copyright © 2020-2023  润新知