poj 1236强连通图缩点

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

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>

#define maxn 105
#define INF  0x3f3f3f
using namespace std;

bool G1[maxn][maxn],G2[maxn][maxn];
vector<int> s;
int vis[maxn],sccnum[maxn],scc_cnt;
int N;
int in[maxn],out[maxn];

/* 
void dfs(int u){
    vis[u] = true;
    for(int i=1;i<=N;i++){
        if(!vis[i]){
            dfs(i);
        }
    }
}*/
void dfs1(int u){
    if(vis[u])  return;
    vis[u] = 1;
    for(int i=1;i<=N;i++){
        if(G1[u][i]){
            dfs1(i); 
        }
    }    //printf("u %d\n",u); 
    s.push_back(u);
}
void dfs2(int u){
    if(sccnum[u])  return;
    sccnum[u] = scc_cnt;  //printf("***  %d  %d\n",u,scc_cnt);
    for(int i=1;i<=N;i++)
       if(G2[u][i]) { //printf("i  %d\n",i);
              dfs2(i);
       } 
}
void Get_new_graph(){
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for(int i=1;i<=N;i++)
      for(int j=1;j<=N;j++){
          if(sccnum[i] != sccnum[j] && G1[i][j]){
              in[sccnum[j]]++;
              out[sccnum[i]]++;
        }
      }
}
void find_scc(){
    scc_cnt = 0;
    s.clear();
    memset(sccnum,0,sizeof(sccnum));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=N;i++) dfs1(i); 
    for(int i=N-1;i>=0;i--){  //还不能理解这个关于dfs 
        if(!sccnum[s[i]]){
            scc_cnt++;  //printf("s[i]   %d\n",s[i]);
            dfs2(s[i]);
        } 
    }
    Get_new_graph();
}
int main()
{
    freopen("input.txt","r",stdin);
    scanf("%d",&N);
    memset(G1,0,sizeof(G1));
    memset(G2,0,sizeof(G2));
    for(int i=1;i<=N;i++){
        int a;
        while(scanf("%d",&a) && a){
            G1[i][a] = true;
            G2[a][i] = true;
        }
    }
    /*  
    int bcc_cnt = 0;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=N;i++){
        if(!vis[i]){
            bcc_cnt++;
            dfs(i);
        }
    }*/   //本题只有一个联通分量; 
    find_scc();
    int ansb = 0;
    int innum = 0,outnum = 0;
    for(int i=1;i<=scc_cnt;i++){
        if(in[i] == 0)  innum++;
        if(out[i] == 0) outnum++;
    }   
    if(scc_cnt == 1) printf("1\n0\n");  //这个地方就是WA的原因。 
    else{
        printf("%d\n",innum);
        printf("%d\n",max(innum,outnum));
    }
} 
View Code

 

posted @ 2013-08-02 01:00  等待最好的两个人  阅读(153)  评论(0编辑  收藏  举报