UOJ67 新年的毒瘤

本文版权归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;
}

  

原文地址:https://www.cnblogs.com/ljh2000-jump/p/6357317.html