CF1364D Solution

题目链接

题解

依题目所述,2种完成方法一定可以满足一种,以下为简单证明:若图中存在简单环,设该环长度为\(l\)。若\(l\le k\),则满足条件1;若\(l>k\),间隔取点可以得到包含\(\lfloor \frac{l}{2}\rfloor\)个点的独立集,又因为\(\lfloor \frac{l}{2}\rfloor\ge \lceil \frac{k}{2}\rceil\),满足条件2。如果图中不存在环,则该图为二分图(树),一定满足条件1。

上述证明正可以成为我们的解题思路(出题人伏笔妙a),具体实现:dfs找出图中的一个环,利用栈记录搜索到的全部节点,如果同一节点经过2次则判断为环,递归后回溯则可保证不会出现多余节点。如果没有找到环说明这是一棵树,黑白染色(使节点与其祖先不为同一颜色)后取节点数较多的颜色输出即可。如果找到环的话,仍需注意我们记录的只是节点,其可能构成的不是简单环。为此遍历所有环中的节点,如果其存在一条不在环中的边通向环中其他节点,则将该边另一侧全部节点删去,将此边加入。对于找出的简单环,若\(l>k\)则隔一个点输出一个(条件2),若\(l\le k\)则直接将该环输出(条件1)。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=2e5+10;
int fst[N],nxt[2*M],v[2*M],cnt;
int st[N],top;
int r[N];
bool vis[N],c[N];
void add(int x,int y)
{
	v[++cnt]=y;
	nxt[cnt]=fst[x]; fst[x]=cnt;
}
bool dfs(int x,int fa)
{
	st[++top]=x;
	if(vis[x]) return 1;
	vis[x]=1;
	for(int i=fst[x];i;i=nxt[i])
	{
		int y=v[i];
		if(y==fa) continue; 
		if(dfs(y,x)) return 1;
	} 
	top--; vis[x]=0;
	return 0;
}
void dfs2(int x,int fa)
{
	for(int i=fst[x];i;i=nxt[i])
	{
		int y=v[i];
		if(y!=fa) {c[y]=c[x]^1; dfs2(y,x);}
	}
}
int main()
{
	int n,m,k;
	scanf("%d%d%d",&n,&m,&k);
	int x,y,sum=0;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y),add(y,x); 
	}
	if(!dfs(1,0))
	{
		printf("1\n");
		c[1]=0; dfs2(1,0);
		for(int i=1;i<=n;i++) sum+=c[i];
		k=(k+1)/2;
		if(sum>=k)
		{
			for(int i=1;i<=n && k;i++)
				if(c[i]) {printf("%d ",i); k--;}
			return 0;
		}
		for(int i=1;i<=n && k;i++)
			if(!c[i]) {printf("%d ",i); k--;}
		return 0;
	}
	int qwq=st[top],tot=0;  
	while(st[--top]!=qwq) r[st[top]]=st[top+1],c[st[top]]=1;
	c[qwq]=1,r[qwq]=st[top+1];
	for(int i=1;i<=n;i++)
	{
		if(!c[i]) continue;
		for(int j=fst[i];j;j=nxt[j])
		{
			int y=v[j],pos=r[y];
			if(!c[y] || y==r[i] || r[y]==i) continue;
			while(pos!=i) {c[pos]=0; pos=r[pos];}
			r[y]=i;
		}
	}
	for(int i=1;i<=n;i++) 
	{
		tot+=c[i];
		if(c[i]) qwq=i; 
	}
	if(tot>k)
	{
		printf("1\n"); k=(k+1)/2;
		while(k--) {printf("%d ",qwq); qwq=r[r[qwq]];}
		return 0;
	}
	printf("2\n%d\n%d ",tot,qwq);
	int pos=r[qwq];
	while(pos!=qwq) {printf("%d ",pos); pos=r[pos];}
	return 0;
}
posted @ 2021-02-25 22:20  violet_holmes  阅读(40)  评论(0编辑  收藏  举报