/*
Author : lcy
Time : 2017-10-2
poj1236 强连通分量
给出一个有向图,有两问:
1.第一问转化为求入度为0的点的个数
2.第二问在缩点后,转化为求最少添加多少条边,使得DAG转化为强连通图
max(入度为0的点的个数,出度为0的点的个数)为第二问的答案
要想转化为强连通图,图中至少存在一回路包含所有的点,所以入读为0或出度为0的点
都应是不存在的,所以在他们之间最少添加的边数即为答案。
存在性证明。。。日后补上(估计补不上
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
using namespace std;
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
#define pb(a) push_back(a)
// #define DEBUG
using namespace std;
const int MAXN=105;
int dfn[MAXN],low[MAXN],fa[MAXN],tot;
bool v[MAXN],ins[MAXN];
vector<int>g[MAXN];
stack<int>s;
int n;
void tarjan(int x){
    low[x]=dfn[x]=++tot;
    s.push(x);ins[x]=true;
    int sz=g[x].size();
    fr(i,0,sz-1){
        int t=g[x][i];
        if(v[t])continue;
        else if(ins[t])
            low[x]=min(low[x],dfn[t]);
        else{
            tarjan(t);
            low[x]=min(low[x],low[t]);
        }
    }
    if(low[x]==dfn[x]){
        int t;
        do{
            t=s.top();s.pop();
            fa[t]=x;ins[t]=false;v[t]=true;
        }while(t!=x);
    }
}
void add_edge(int a,int b){
    g[a].pb(b);
}
void init(){
    ms(v,false);
    ms(ins,false);
}
void solve(){
    fr(i,1,n)
        if(!dfn[i])
            tarjan(i);
    int cnt1,cnt2;
    cnt1=cnt2=0;
    int in[MAXN],out[MAXN];
    fr(i,0,MAXN-1)in[i]=out[i]=-1;
    fr(i,1,n){
        if(in[fa[i]]==-1)
            in[fa[i]]=out[fa[i]]=0;
        int sz=g[i].size();
        fr(j,0,sz-1){
            if(fa[g[i][j]]!=fa[i]){
                if(in[fa[g[i][j]]]==-1)
                    in[fa[g[i][j]]]=out[fa[g[i][j]]]=0;
                in[fa[g[i][j]]]++;
                out[fa[i]]++;
            }
        }
    }
    int chk=fa[1];
    bool f=false;
    fr(i,1,n){
        if(chk!=fa[i])
            f=true;
        if(!in[i])
            cnt1++;
        if(!out[i])
            cnt2++;
    }
    if(!f)
        printf("1\n0\n");
    else
    printf("%d\n%d\n",cnt1,max(cnt1,cnt2));
}
int main(){
    init();
    scanf("%d",&n);
    fr(i,1,n){
        int t;
        while(scfd(&t)&&t)add_edge(i,t);
    }
    solve();
    #ifdef DEBUG
    fr(i,1,n)
        printf("%d ",fa[i]);
    printf("\n");
    #endif
    return 0;
}
 posted on 2017-10-02 12:26  cylcy  阅读(124)  评论(0)    收藏  举报