强连通分量的求解,虽说第一眼一看数据量就知道能用Floyd写,但是谁让我太渣呢,还是别偷懒了。熟悉下tarjan。
/* ID: modengd1 PROG: schlnet LANG: C++ */ #include <iostream> #include <stdio.h> #include <vector> #include <stack> #include <memory.h> using namespace std; bool vis[101]; bool insatck[101]; vector<int> G[101]; int N; int dfn[101]; int low[101]; stack<int> ST; int index; int colored[101]; int color; int newG[101][101]; void tarjan(int u) { vis[u]=true; low[u]=dfn[u]=++index; ST.push(u); insatck[u]=true; for(int i=0;i<G[u].size();i++) { if(!vis[G[u][i]]) { tarjan(G[u][i]); low[u]=min(low[G[u][i]],low[u]); } else if(insatck[G[u][i]]) { low[u]=min(low[u],dfn[G[u][i]]); } } if(low[u]==dfn[u])//同一个联通分量中的点染成一个颜色 { color++; while(ST.top()!=u) { colored[ST.top()]=color; insatck[ST.top()]=false; ST.pop(); } colored[ST.top()]=color; insatck[ST.top()]=false; ST.pop(); } } void buildnew() { memset(newG,false,sizeof(newG)); for(int i=1;i<=N;i++) { for(int j=0;j<G[i].size();j++) { if(colored[i]!=colored[G[i][j]]) newG[colored[i]][colored[G[i][j]]]=true; } } int cterO[101],cterI[101]; memset(cterO,0,sizeof(cterO)); memset(cterI,0,sizeof(cterI)); for(int i=1;i<=color;i++) { for(int j=1;j<=color;j++) { if(newG[i][j]) { cterO[i]++; cterI[j]++; } } } int ans0=0,ans1=0; for(int i=1;i<=color;i++) { if(cterI[i]==0)//入度为零的点的个数 ans0++; if(cterO[i]==0)//出度为零的点的个数 ans1++; } if(color==0) { cout<<1<<endl<<0<<endl; } else { cout<<ans0<<endl<<max(ans0,ans1)<<endl; } } int main() { freopen("schlnet.in","r",stdin); freopen("schlnet.out","w",stdout); scanf("%d",&N); for(int i=1;i<=N;i++) { int v; while(scanf("%d",&v)&&v!=0) { G[i].push_back(v); } } index=0; color=0; memset(colored,0,sizeof(color)); for(int i=1;i<=N;i++) { if(colored[i]==0) tarjan(i); } buildnew(); return 0; }
时间: 2024-10-13 00:48:09