zoukankan      html  css  js  c++  java
  • hdu 1827 有向图缩点看度数

    题意:给一个有向图,选最少的点(同时最小价值),从这些点出发可以遍历所有。
    思路:先有向图缩点,成有向树,找入度为0的点即可。
    下面给出有向图缩点方法:

    用一个数组SCC记录即可,重新编号,1....num,具体方法如下代码详见。


    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    using namespace std;
    int n,m;
    vector<vector<int> >v(10010);
    int vis[10010];int dfn[10010];int low[10010];int times=0;
    int num=0;
    int instack[10010];stack<int>s;   //有向图的连通性,用栈。
    int scc[1010]; int w[1010]; int neww[1010];
    int ind[1010];
    void tarjarn(int u)
    {
       dfn[u]=low[u]=++times;
       instack[u]=1;
       s.push(u);
       for(int i=0;i<v[u].size();i++)
       {
           int vv=v[u][i];
           if(!vis[vv])
           {
               vis[vv]=1;
               tarjarn(vv);
               if(low[vv]<low[u])low[u]=low[vv];  //孩子可以到达,我必然也可以到达。
           }
           else if(instack[vv])      //注意,更新时要有在栈中条件,代表该孩子(其实是祖先)我能到达,而且是属于当前SCC。
           {
               if(dfn[vv]<low[u])low[u]=dfn[vv]; //能到达的祖先,所以更新。
           }
       }
       if(dfn[u]==low[u])    
       {
           num++;int cur;
           int min=w[u];   //找这个SCC权最小的权。
           do
           {
               cur=s.top();
               if(w[cur]<min)min=w[cur];
               s.pop();
               instack[cur]=0;
               scc[cur]=num;
           }while(cur!=u);
           neww[num]=min;
       }
    }
    int main()
    {
        while(~scanf("%d %d",&n,&m))
        {
            int ta,tb;
            for(int i=0;i<=n;i++)
              {
                  v[i].clear();
                  neww[i]=ind[i]=w[i]=instack[i]=dfn[i]=low[i]=vis[i]=0;
              }
              times=0;
           for(int i=1;i<=n;i++)
           {
              scanf("%d",&w[i]);
           }
            for(int i=0;i<m;i++)
            {
                scanf("%d %d",&ta,&tb);
                v[ta].push_back(tb);
            }
            num=0;
            for(int i=1;i<=n;i++)
             {
                   if(!vis[i])
                       {   vis[i]=1;
                           tarjarn(i);
                       }
             }
             int sum=0;int count=0; 
            for(int i=1;i<=n;i++)           //遍历边。
            {
                for(int j=0;j<v[i].size();j++)
                 {
                     if(scc[i]!=scc[v[i][j]])
                       {
                         ind[scc[v[i][j]]]++;
                       }
                 }
            }
             for(int i=1;i<=num;i++)
            {
                if(ind[i]==0)
                {
                    sum+=neww[i];
                    count++;
                }
            }
            printf("%d %d
    ",count, sum);
        }
        return 0;
    }
    



  • 相关阅读:
    团队项目冲刺第九天
    团队项目冲刺第八天
    团队项目冲刺第七天
    团队项目冲刺第六天
    vue-cli(vue脚手架)详细教程
    Ocelot+Consul 集群搭建实践
    docker部署net core项目
    nginx配置文件
    条码扫描器
    转载:MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925719.html
Copyright © 2011-2022 走看看