• Codeforces Round #649 (Div. 2) D. Ehab's Last Corollary


    题意:

    给一个无向图,不含重边和自环,现在给出一个整数 (k) ,现在有两个问题:

    1. 在图中找到大小为 (lceil frac{k}{2} ceil) 的独立点集;
    2. 在图中找到长度不超过 (k) 的环;

    其中独立点集即集合中任意两点之间没有边;给出的无向图至少满足上面两种情况之一,现在要求你解决其中一个问题(自选),并输出具体答案,问题 (1) 输出独立点集,问题 (2) 按顺序输出环;

    分析:

    (dfs) 的同时用递归深度做权值判断每个环的大小,找到符合问题 (2) 的环就直接输出结束程序,否则随便找个点开始构建独立点集就好了;

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define frep(i,a,b) for(int i=a;i>=b;i--)
    const int N = 1E5+10;
    vector<int>G[N]; 
    int n,k,m,lev[N],pt[N],cnt=0,vis[N];
    
    void dfs(int u,int pre)
    {
    	pt[++cnt]=u;  //当前递归深度为cnt的节点
    	lev[u]=cnt;   //节点u的递归深度
    	for(int v:G[u])
    	{
    		if(v==pre) continue;
    		if(!lev[v]) dfs(v,u); //节点v没有访问过,就继续dfs
    		//否则,那么节点v-u构成一个环,长度为lev[u]-lev[v]+1
    		else if(lev[u]-lev[v]+1>=0&&lev[u]-lev[v]+1<=k)
    		{
    			cout<<2<<endl<<lev[u]-lev[v]+1<<endl;
    			for(int i=lev[v];i<=lev[u];i++)
    			cout<<pt[i]<<" ";
    			exit(0); 
    		}
    	}
    	/*
    	  如果这个点没有被标记过,那么它就是独立点集之一,并把所有相邻的点标记;
    	  这里相当于dfs到最深处然后反向构建独立点集,理由是保证了所有只有一个边
    	  的点都被选进独立点集,这样的选择总是最优的
    	*/
    	if(!vis[u])  
    	  for(auto v:G[u]) vis[v]=1;
    	--cnt;
    }
    
    int main()
    {
    	//freopen("1.txt","r",stdin);
    	ios::sync_with_stdio(false);
    	cin.tie(0),cout.tie(0);
    	
    	cin>>n>>m>>k;
    	rep(i,1,m){
    		int u,v;
    		cin>>u>>v;
    		G[u].pb(v);
    		G[v].pb(u);
    	}
    	dfs(1,0);
    	k=(k+1)/2;
    	cout<<1<<endl;
    	rep(i,1,n)if(!vis[i]){
    		cout<<i<<" ";
    		if(--k==0) break;
    	}
    } 
    
  • 相关阅读:
    Ubuntu1404: 将VIM打造为一个实用的PythonIDE
    事前备份胜于事后恢复
    做事不应当拘泥于既定的循例
    简单生活
    《犹太人思考术》读后感
    产品开发与运维的中心准则
    Awk使用一例:获取ASCII可见字符
    使用Sed和Awk实现批量文件的文本替换
    编写更少bug的程序的六条准则
    【JS新手教程】JS中的split()方法,拆分字符串
  • 原文地址:https://www.cnblogs.com/17134h/p/13185537.html
Copyright © 2020-2023  润新知