题目链接: 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 }