zoukankan      html  css  js  c++  java
  • poj 2186(强连通分量)

    题意:
    n头奶牛,给出若干个欢迎关系a b,表示a欢迎b,欢迎关系是单向的,但是是可以传递的,如:a欢迎b,b欢迎c,那么a欢迎c 。另外每个奶牛都是欢迎他自己的。求出被所有的奶牛欢迎的奶牛的数目.

    方法:对有向图求强连通分量,然后找出所有独立的强连通分量(所谓独立,就是该连通分量里面的点到外面的点没有通路,当然,连通分量外的点是可以有路到强连通分量内的点的),如果独立的强连通分量的数目只有一个,那么,就输出这个强连通分量内解的个数,否则输出无解。

    kosaraju:

    http://www.nocow.cn/index.php/Kosaraju%E7%AE%97%E6%B3%95

    View Code
      1 // File Name: 2186.cpp
      2 // Author: Missa
      3 // Created Time: 2013/2/5 星期二 20:47:56
      4 
      5 #include<iostream>
      6 #include<cstdio>
      7 #include<cstring>
      8 #include<algorithm>
      9 #include<cmath>
     10 #include<queue>
     11 #include<stack>
     12 #include<string>
     13 #include<vector>
     14 #include<cstdlib>
     15 #include<map>
     16 using namespace std;
     17 
     18 //***********************kosaraju**************
     19 const int maxn = 1e4+5;
     20 const int maxm = 5e4+5;
     21 int n,m;
     22 vector <int> adj[maxn];//正向邻接表
     23 vector <int> radj[maxn];//反向邻接表
     24 vector <int> ord;//后续访问顺序
     25 bool vis[maxn];
     26 int ma[maxn];//表示点v属于哪个连通分量
     27 int cnt;//有向图强连通分量的个数
     28 void init()
     29 {
     30     for(int i=0;i<maxn;i++)
     31     {
     32         adj[i].clear();
     33         radj[i].clear();
     34     }
     35     ord.clear();
     36     cnt=0;
     37 }
     38 void dfs1(int v)
     39 {
     40     vis[v]=1;
     41     for(int i=0;i<adj[v].size();i++)
     42         if(!vis[adj[v][i]])
     43             dfs1(adj[v][i]);
     44     ord.push_back(v);
     45 }
     46 void dfs2(int v)
     47 {
     48     vis[v]=1;
     49     ma[v]=cnt;
     50     for(int i=0;i<radj[v].size();i++)
     51         if(!vis[radj[v][i]])
     52             dfs2(radj[v][i]);
     53 }
     54 void kosaraju()
     55 {
     56     memset(vis,0,sizeof(vis));
     57     ord.clear();
     58     for(int i=1;i<=n;i++)//顶点从1--n
     59         if(!vis[i])
     60             dfs1(i);
     61     memset(vis,0,sizeof(vis));
     62     cnt=0;
     63     for(int i=ord.size()-1;i>=0;i--)
     64         if(!vis[ord[i]])
     65         {
     66             cnt++;
     67             dfs2(ord[i]);
     68         }
     69 }
     70 //*********************************************
     71 void solve()
     72 {
     73     kosaraju();
     74     int ans[maxn];
     75     memset(vis,0,sizeof(vis));
     76     memset(ans,0,sizeof(ans));
     77     for(int i=1;i<=n;i++)
     78     {
     79         ans[ma[i]]++;//统计每个连通分量的大小
     80         for(int j=0;j<adj[i].size();j++)
     81         {
     82             int v=adj[i][j];
     83             if(ma[i] != ma[v])//有向边(i,v),若i与v不在一个连通分量
     84                 vis[ma[i]]=1;//i所在的强连通分量出度不为0.
     85         }
     86     }
     87     int flag=0,cow;
     88     for(int i=1;i<=cnt;i++)
     89     {
     90         if(!vis[i])//出度为0
     91         {
     92             cow=i;
     93             flag++;
     94         }
     95     }
     96     if(flag==1)
     97         printf("%d\n",ans[cow]);
     98     else
     99         printf("0\n");//存在多个出度为0。表明至少两组是不互相羡慕的
    100 }
    101 int main()
    102 {
    103     while(~scanf("%d%d",&n,&m))
    104     {
    105         init();
    106         for(int i=0;i<m;i++)
    107         {
    108             int x,y;
    109             scanf("%d%d",&x,&y);
    110             adj[x].push_back(y);
    111             radj[y].push_back(x);//反向边
    112         }
    113         solve();
    114     }
    115     return 0;
    116 }
    117 
    118 /*
    119 3 3
    120 1 2
    121 2 1
    122 2 3
    123  * /
  • 相关阅读:
    转:wcf大文件传输解决之道(1)
    转:WCF传送二进制流数据基本实现步骤详解
    创建一个简单的WCF程序2——手动开启/关闭WCF服务与动态调用WCF地址
    创建一个简单的WCF程序
    转:【专题十二】实现一个简单的FTP服务器
    转:【专题十一】实现一个基于FTP协议的程序——文件上传下载器
    转:【专题十】实现简单的邮件收发器
    转:【专题九】实现类似QQ的即时通信程序
    转:【专题八】P2P编程
    转:【专题七】UDP编程补充——UDP广播程序的实现
  • 原文地址:https://www.cnblogs.com/Missa/p/2893425.html
Copyright © 2011-2022 走看看