zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    mybatis记录随便(五)一对多映射实现方式
    mybatis记录随便(四)一对一映射实现方式
    mybatis记录随便(三)foreach实现in查询
    mybatis记录随便(二)insert获取主键方法
    mybatis记录随便(一)resultMap配置说明
    SpringBoot2.0与Shrio集成实战操作
    从实战的角度谈微服务(六):对于消息中间件RabbitMQ的基本使用
    从实战的角度谈微服务(五):使用Zuul创建微服务网关、添加熔断
    从实战的角度谈微服务(四):使用Spring Boot Admin监控服务(Spring Boot 2.0,基于 Eureka 的实现)
    SpringBoot随笔(一)-controller接收多个实体解决方案
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14449692.html
Copyright © 2011-2022 走看看