• Poj 2186 Popular Cows


    http://poj.org/problem?id=2186

    题意:给定N头牛和M个有序对(A,B)。每头牛都想成为牛群中的popular。(A,B)表示牛A认为牛B是popular。且关系具有传递性,eg:如果A认为B是popular,B认为C是popular,则A认为C是popular。求被其他所有牛认为是popular牛的总数。

    题解:是一道典型求强连通分量的题。把图进行强连通分量分解后,至多有一个强连通分量满足题目的条件。得到各个强连通分量拓扑排序后的顺序,唯一可能成为解的只有拓扑排序后的强连通分量。所以只需检查这个强连通分量是否可以从所有顶点到达即可。(求强连通分量用的不是大多数人用的tarjan……而是Kosaraju。Kosaraju与tarjan区别在于Kosaraju需要建立逆图,进行两次DFS。

    补充:详细tarjan介绍:http://blog.csdn.net/wsniyufang/article/details/6604458

      1 //
      2 //  main.cpp
      3 //  POJ 2186
      4 //
      5 //  Created by zhang on 14-4-9.
      6 //  Copyright (c) 2014年 apple. All rights reserved.
      7 //
      8 
      9 #include <iostream>
     10 #include <cstring>
     11 #include <cstdio>
     12 #include <cstdlib>
     13 #include <cmath>
     14 #include <string>
     15 #include <vector>
     16 #include <list>
     17 #include <map>
     18 #include <queue>
     19 #include <stack>
     20 #include <bitset>
     21 #include <algorithm>
     22 #include <numeric>
     23 #include <functional>
     24 #include <set>
     25 #include <fstream>
     26 
     27 using namespace std;
     28 
     29 const int maxn=50010;
     30 int A[maxn],B[maxn];
     31 int V;
     32 vector<int> G[maxn];
     33 vector<int> rG[maxn];
     34 vector<int> vs;
     35 bool used [maxn];
     36 int cmp[maxn];//所属强连通分量的拓扑序
     37 int N,M;
     38 void add_edge(int from,int to)
     39 {
     40     G[from].push_back(to);
     41     rG[to].push_back(from);
     42 }
     43 
     44 void dfs(int v)
     45 {
     46     used[v]=true;
     47     for (int i=0; i<G[v].size(); i++) {
     48         if (!used[G[v][i]]) {
     49             dfs(G[v][i]);
     50         }
     51     }
     52     vs.push_back(v);
     53 }
     54 
     55 void rdfs(int v,int k)
     56 {
     57     used[v]=true;
     58     cmp[v]=k;
     59     for (int i=0; i<rG[v].size(); i++) {
     60         if (!used[rG[v][i]]) {
     61             rdfs(rG[v][i], k);
     62         }
     63     }
     64 }
     65 
     66 int scc()
     67 {
     68     memset(used, 0, sizeof(used));
     69     vs.clear();
     70     for (int v=0; v<V; v++) {
     71         if (!used[v]) {
     72             dfs(v);
     73         }
     74     }
     75     memset(used, 0, sizeof(used));
     76     int k=0;
     77     for (int i=vs.size()-1; i>=0; i--) {
     78         if (!used[vs[i]]) {
     79             rdfs(vs[i], k++);
     80         }
     81     }
     82     return k;
     83 }
     84 
     85 //void solve()
     86 //{
     87 
     88 //}
     89 int main()
     90 {
     91     scanf("%d%d",&N,&M);
     92     for (int i=0; i<M; i++) {
     93         scanf("%d%d",&A[i],&B[i]);
     94         add_edge(A[i]-1, B[i]-1);
     95     }
     96     V=N;
     97     int n=scc();
     98     int u=0,num=0;
     99     for (int v=0; v<V; v++) {
    100         if (cmp[v]==n-1) {
    101             u=v;
    102             num++;
    103         }
    104     }
    105     memset(used, 0, sizeof(used));
    106     rdfs(u, 0);
    107     for (int v=0; v<V; v++) {
    108         if (!used[v]) {
    109             num=0;
    110             break;
    111         }
    112     }
    113     
    114     printf("%d
    ",num);
    115 
    116     return 0;
    117 }
  • 相关阅读:
    05 drf源码剖析之认证
    04 drf源码剖析之版本
    03 drf源码剖析之视图
    02 drf源码剖析之快速了解drf
    OA之为用户设置角色和为用户设置权限
    EasyUI之datagrid的使用
    C#之反射
    EasyUI之Layout布局和Tabs页签的使用
    Memcached的使用
    Log4Net的简单使用
  • 原文地址:https://www.cnblogs.com/der-z/p/3654974.html
Copyright © 2020-2023  润新知