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;
    }
    



  • 相关阅读:
    VS 2008潜在强大的功能:提取EXE文件中的ICO等资源
    园友们注意:淘宝网上QQ会员 4钻 3元 等都为骗子行为
    Comet Async Process Request Handler
    WCF(Sender) to MSMQ to WCF(Receiver)
    ASP.NET Web Form GridView DetailsView Query Edit
    WCF NetTcp AsyncQueue Service
    Xml CDATA 序列化
    Sync Invoke Remoting Async Invoke
    .Net 4.0 Remoting ConcurrentQueue
    Socket Async Receive Data to LinkedList Buffer (telnet proxy server)
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925719.html
Copyright © 2011-2022 走看看