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)); } }