坐井观天

In the name of dream

导航

POJ 1236 Tarjan缩点+求度数

Posted on 2012-04-17 12:52  一毛_  阅读(382)  评论(0编辑  收藏  举报

题目链接: http://poj.org/problem?id=1236

题目大意:

  给定一个n (n<=100)个点的有向图,问:
  Q1、最少需要选择多少个点,使得从这些点出发能遍历完整个图;
  Q2、最少需要添加多少条有向边,使得整个图成为连通图;

分析:

        开始Q1我想复杂了,先说Q2吧,和hdu2767一样,当时我自己ac了hdu2767,可是做Q2的时候又一下没想到,便找出了原来的代码……

        先由Tarjan算法求出强连通分量后进行缩点,得到每个强连通分量的入度in[],出度out[];

  Q1: 入度为0的强连通分量个数;  

  Q2: max(  入度为0的强连通分量个数 ,  出度为0的强连通分量个数  );

代码:

poj1236
  1 /*1236    Accepted    264K    32MS    C++    2408B    2012-04-17 12:29:23*/
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <vector>
  8 using namespace std;
  9 
 10 #define mpair make_pair
 11 #define pii pair<int,int>
 12 #define MM(a,b) memset(a,b,sizeof(a));
 13 typedef long long lld;
 14 typedef unsigned long long u64;
 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
 17 #define maxn 110
 18 
 19 int n;
 20 vector<int> adj[maxn];
 21 
 22 bool vis[maxn];
 23 int Bcnt, Top, Index;
 24 int stack[maxn], low[maxn], dfn[maxn];
 25 int belong[maxn];
 26 void Init_tarjan(){
 27     Bcnt= Top= Index= 0;
 28     for(int i=1;i<=n;++i) low[i]= dfn[i]= vis[i]= 0;
 29 }
 30 void Tarjan(int u){
 31     vis[u]= 1; /// push() into stack;
 32     stack[++Top]= u;
 33     low[u]= dfn[u]= ++Index;
 34     for(int i=0;i<adj[u].size();++i){
 35         int v= adj[u][i];
 36         if( !dfn[v] ){
 37             Tarjan( v );
 38             up_min( low[u], low[v] );
 39         }
 40         else if( vis[v] )
 41             up_min( low[u], dfn[v] );
 42     }
 43     if( low[u]==dfn[u] ){
 44         ++Bcnt;
 45         int v;
 46         do{
 47             v= stack[Top--];
 48             belong[v]= Bcnt;
 49             vis[v]= 0; /// pop() from stack;
 50         }while( u!=v );
 51     }
 52 }
 53 
 54 int in[maxn], out[maxn];
 55 void dfs(int u){;
 56     vis[u]= 1;
 57     for(int i=0;i<adj[u].size();++i){
 58         int v= adj[u][i];
 59         if( belong[u] !=belong[v] ){
 60             out[ belong[u] ]++;
 61             in[ belong[v] ]++;
 62         }
 63         if( !vis[v] )
 64             dfs( v );
 65     }
 66 }
 67 
 68 int main()
 69 {
 70     //freopen("1236.in","r",stdin);
 71     int i,t;
 72     while(cin>>n){
 73         for(i=1;i<=n;++i) adj[i].clear();
 74         for(i=1;i<=n;++i){
 75             while( scanf("%d", &t), t )
 76                 adj[i].push_back( t );
 77         }
 78 
 79         Init_tarjan();
 80         for(i=1;i<=n;++i)
 81             if( !dfn[i] ){ /// dfn[i]!!!
 82                 Tarjan(i);
 83             }
 84 
 85         if( 1==Bcnt ){ ///
 86             puts("1\n0");
 87             continue;
 88         }
 89 
 90         for(i=1;i<=Bcnt;++i) in[i]= out[i]= 0;
 91         fill( vis+1, vis+1+n, 0 );
 92         for(i=1;i<=n;++i){
 93             if( !vis[i] )
 94                 dfs(i);
 95         }
 96 
 97         int s1=0, s2=0;
 98         for(i=1;i<=Bcnt;++i){
 99             if( 0==in[i] ) s1++;
100             if( 0==out[i] ) s2++;
101         }
102         printf("%d\n%d\n", s1, max(s1,s2) );
103     }
104 }