http://acm.timus.ru/problem.aspx?space=1&num=1198
英语真的是硬伤呀 读了N遍 愣是没有读懂 最后看了别人的提示
反正是联通分量 缩点 然后对缩点后的图进行求解 缩点后的图必须有且仅有一个点入度为0
然后输出这个入度为0的点所包含的所有原来的点 (按顺序)
注意输入数据量很多 要用scanf 用cin 有可能超时
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<set> #include<map> #include<queue> #include<algorithm> #include<cmath> #define LL long long //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int N=2005; const int INF=0x3f3f3f3f; //typedef pair<int,int>point; int head[N],I; struct node { int j,next; }side[N*2000]; int dfn[N],low[N],f[N],deep; bool visited[N],in[N]; int sum[N]; stack<int>st; void add(int i,int j) { side[I].j=j; side[I].next=head[i]; head[i]=I++; } void dfs(int x) { dfn[x]=low[x]=deep++; st.push(x); in[x]=true; visited[x]=true; for(int t=head[x];t!=-1;t=side[t].next) { int j=side[t].j; if(!visited[j]) { dfs(j); low[x]=min(low[x],low[j]); }else if(in[j]) { low[x]=min(low[x],dfn[j]); } } if(low[x]==dfn[x]) { while(st.top()!=x) { in[st.top()]=false; f[st.top()]=x; st.pop(); } in[st.top()]=false; f[st.top()]=x; st.pop(); } } int main() { int n; while(scanf("%d",&n)!=EOF) { memset(head,-1,sizeof(head)); I=0; for(int i=1;i<=n;++i) { int k; while(scanf("%d",&k)) { if(k==0) break; add(i,k); } } while(!st.empty()) st.pop(); memset(in,false,sizeof(in)); memset(visited ,false,sizeof(visited)); deep=1; for(int i=1;i<=n;++i) if(!visited[i]) dfs(i); memset(sum,0,sizeof(sum)); for(int i=1;i<=n;++i) { for(int t=head[i];t!=-1;t=side[t].next) { int j=side[t].j; if(f[i]!=f[j]) ++sum[f[j]]; } } vector<int>vt; int flag=0; for(int i=1;i<=n;++i) if(sum[f[i]]==0) { vt.push_back(i); if(flag==0) flag=f[i]; else if(f[i]!=flag) flag=-1; } if(flag>0) { sort(vt.begin(),vt.end()); for(unsigned int i=0;i<vt.size();++i) cout<<vt[i]<<" "; } cout<<"0"<<endl; } }