zoukankan      html  css  js  c++  java
  • Codeforces 521E. Cycling City 题解

    题目链接:E. Cycling City

    题目大意:洛谷


    题解:经过翻题解画图可以发现,一张图不存在这样的路径当且仅当这张图是一个沙漠。如何判断一张联通图是不是仙人掌很简单,任意求出一棵生成树后,将不在生成树上的边加 1 ,如果没有权值超过 1 的边,那么这一张图就是一个仙人掌。

    那么接下来的主要问题就是如何构造答案,思路比较清晰,就是找出任意两个环相交的一条链,这一条链很明显可以通过三种方式找到,所以接下来的问题就是怎么找这一条链以及这两个环,首先,我们找到在上一个步骤中权值大于 1 的,在生成树上深度最小的边,选取最小的边的原因是在它一定会是最终答案的那条链的起点,然后暴力往下找到任意两个环,记录环中深度最小的点和深度最大的点(你也可以理解为记录环上唯一一条不在生成树上的边),然后链的终点就是两个环上深度最大的点的 LCA ,这里直接暴力就可以了,然后路径就非常好找了,因为大部分的边都在生成树上,唯二不在生成树上的边已经被记录下来了。

    时间复杂度(O(n))

    代码:

    #include <vector>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    void read(int &a){
    	a=0;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		a=(a<<1)+(a<<3)+(c^48);
    		c=getchar();
    	}
    }
    const int Maxn=200000;
    int head[Maxn+5],arrive[Maxn<<1|5],nxt[Maxn<<1|5],tot;
    void add_edge(int from,int to){
    	arrive[++tot]=to;
    	nxt[tot]=head[from];
    	head[from]=tot;
    }
    int n,m;
    int sum[Maxn+5];
    int fa[Maxn+5];
    int dep[Maxn+5];
    void init_dfs(int u){
    	dep[u]=dep[fa[u]]+1;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=arrive[i];
    		if(v==fa[u]){
    			continue;
    		}
    		if(dep[v]==0){
    			fa[v]=u;
    			init_dfs(v);
    			sum[u]+=sum[v];
    		}
    		else if(dep[v]<dep[u]){
    			sum[u]++;
    			sum[v]--;
    		}
    	}
    }
    int start,bottom;
    struct Edge{
    	int u,v;
    }edge[5];
    int len;
    void work_dfs(int u){
    	for(int i=head[u];i;i=nxt[i]){
    		int v=arrive[i];
    		if(v==fa[u]){
    			continue;
    		}
    		if(dep[v]==dep[u]+1){
    			work_dfs(v);
    		}
    		else if(dep[v]<dep[start]){
    			edge[++len].u=u;
    			edge[len].v=v;
    		}
    		if(len>=2){
    			break;
    		}
    	}
    }
    vector<int> ans[3];
    void calc_path(int u,int v,vector<int>& ans){
    	static vector<int> path;
    	path.clear();
    	bool flag=0;
    	if(dep[u]<dep[v]){
    		swap(u,v);
    		flag=1;
    	}
    	while(u!=v){
    		path.push_back(u);
    		u=fa[u];
    	}
    	path.push_back(v);
    	if(flag){
    		reverse(path.begin(),path.end());
    	}
    	for(int i=0;i<(int)path.size();i++){
    		ans.push_back(path[i]);
    	}
    }
    int main(){
    	read(n),read(m);
    	for(int i=1;i<=m;i++){
    		int u,v;
    		read(u),read(v);
    		add_edge(u,v);
    		add_edge(v,u);
    	}
    	for(int i=1;i<=n;i++){
    		if(fa[i]==0){
    			init_dfs(i);
    		}
    	}
    	for(int i=1;i<=n;i++){
    		if(sum[i]>1&&(start==0||dep[i]<dep[start])){
    			start=i;
    		}
    	}
    	if(start==0){
    		puts("NO");
    		return 0;
    	}
    	work_dfs(start);
    	start=fa[start];
    	int u=edge[1].u,v=edge[2].u;
    	while(u!=v){
    		if(dep[u]>dep[v]){
    			u=fa[u];
    		}
    		else{
    			v=fa[v];
    		}
    	}
    	bottom=u;
    	calc_path(start,bottom,ans[0]);
    	calc_path(start,edge[1].v,ans[1]);
    	calc_path(edge[1].u,bottom,ans[1]);
    	calc_path(start,edge[2].v,ans[2]);
    	calc_path(edge[2].u,bottom,ans[2]);
    	puts("YES");
    	for(int i=0;i<3;i++){
    		printf("%u ",ans[i].size());
    		for(int j=0;j<(int)ans[i].size();j++){
    			printf("%d ",ans[i][j]);
    		}
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux安装kafka教程
    linux 系统java相关部署
    redies学习总结
    Sentinel自定义异常降级-新旧版本差异
    Android Bitmap压缩详解
    Head First之策略模式
    go测试
    go获取命令行参数
    JVM-垃圾收集算法基础
    Java代理模式
  • 原文地址:https://www.cnblogs.com/withhope/p/13593624.html
Copyright © 2011-2022 走看看