本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:http://uoj.ac/problem/67
正解:tarjan+树的相关性质
解题报告:
考虑能变成一棵树,肯定说明至少选择的点不是割点,其次题解里面说了这个点的度数有特定的要求...
那么就变成简单题了...
只需找出不是割点且度数=m-(n-2)的点即可。
注意有一些奇怪的边界条件...
(不要想当然的以为m=n-1答案是0...)
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <complex> using namespace std; typedef long long LL; const int MAXN = 100011; const int MAXM = 200011; int n,m,d[MAXN],ecnt,first[MAXN],next[MAXM],to[MAXM],dfn[MAXN],low[MAXN]; int ans,dui[MAXN]; bool iscut[MAXN]; //需要考虑单独一个点在一个连通块,而其余的点构成一棵树的情况... inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void tarjan(int x,int fa,int rt){ int size=0; dfn[x]=++ecnt; low[x]=dfn[x]; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(v==fa) continue; if(!dfn[v]) { size++;/*!!!*/ tarjan(v,x,rt); if(low[v]>=dfn[x] && x!=rt) iscut[x]=true; low[x]=min(low[x],low[v]); } else low[x]=min(low[x],dfn[v]); } if(size>1 && x==rt) iscut[x]=1; } inline void work(){ n=getint(); m=getint(); int x,y; for(int i=1;i<=m;i++) { x=getint(); y=getint(); d[x]++; d[y]++; next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; } ecnt=0; int LIM=m-(n-2); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1,i); for(int i=1;i<=n;i++) if(d[i]==LIM && (!iscut[i])) dui[++ans]=i; printf("%d ",ans); for(int i=1;i<=ans;i++) printf("%d ",dui[i]); } int main() { work(); return 0; }