• 「CF521E」 Cycling City


    「CF521E」 Cycling City

    传送门

    首先你能发现这个东西一定是两个环的公共边。

    最开始想的是什么如果一个点被访问过三次那它一定是公共边的某一端之类的东西,然后发现被仙人掌叉掉。

    然后就不会了。

    事实上有很简洁的做法:先求出原图的任意一棵 ( exttt{DFS}) 树,然后对于每一条非树边,它一定与一条树上的路径构成一个环,暴力覆盖知道某一条边被经过两次即可。

    根据抽屉原理可得这样的复杂度是正确的,为 (O(n))

    当然我为了方便写的 (O(nlog_2n))

    以后遇到与环相关的问题可以往这个方向上想想。

    贴代码:

    /*---Author:HenryHuang---*/
    /*---Never Settle---*/
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+5;
    struct edge{
    	int to,nex;
    }e[maxn<<1];
    int head[maxn],cnt=1;
    void add(int a,int b){
    	e[++cnt]=(edge){b,head[a]};
    	head[a]=cnt;
    }
    int vis[maxn],t[maxn<<2];
    int dep[maxn],fa[maxn];
    void dfs(int u){
    	dep[u]=dep[fa[u]]+1;vis[u]=1;
    	for(int i=head[u];i;i=e[i].nex){
    		int v=e[i].to;
    		if(!vis[v]){
    			t[i]=t[i^1]=1;
    			fa[v]=u;
    			dfs(v);
    		}
    	}
    }
    int path[maxn],tot;
    void wr(int a,int b){
    	path[++tot]=a;
    	while(a!=b){
    		a=fa[a];
    		path[++tot]=a;
    	}
    	return ;
    }
    void pr(){
    	cout<<tot<<' ';
    	for(int i=1;i<=tot;++i) cout<<path[i]<<' ';
    	cout<<'
    ';tot=0; 
    }
    int lca(int x,int y){
    	while(dep[x]>dep[y]) x=fa[x];
    	while(dep[x]<dep[y]) y=fa[y];
    	while(x!=y) x=fa[x],y=fa[y];
    	return x;
    }
    void print(int a,int b,int c,int d){
    	cout<<"YES
    ";
    	int x=lca(b,d);
    	if(dep[a]>dep[c]) swap(a,c),swap(b,d);
    	wr(x,c);reverse(path+1,path+tot+1);pr();
    	wr(c,a);wr(b,x);pr();
    	path[++tot]=c,wr(d,x);pr();
    	exit(0);
    }
    map<pair<int,int>,pair<int,int> > mp;
    void check(int a,int b){
    	if(dep[a]<dep[b]) swap(a,b);
    	int d=a;
    	while(d!=b){
    		int c=fa[d];
    		if(mp.count(make_pair(c,d)))
    			print(b,a,mp[make_pair(c,d)].first,mp[make_pair(c,d)].second);
    		else mp[make_pair(c,d)]=make_pair(b,a);
    		d=c;
    	}
    }
    int main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	int n,m;cin>>n>>m;
    	for(int i=1;i<=m;++i){
    		int a,b;cin>>a>>b;
    		add(a,b),add(b,a);
    	}
    	for(int i=1;i<=n;++i)
    		if(!vis[i]) dfs(i);
    	for(int u=1;u<=n;++u)
    		for(int i=head[u];i;i=e[i].nex)
    			if(!t[i])
    				check(u,e[i].to),t[i]=t[i^1]=1;
    	cout<<"NO
    ";
    	return 0;
    }
    
    在繁华中沉淀自我,在乱世中静静伫立,一笔一划,雕刻时光。
  • 相关阅读:
    计算机硬件内存双通道只显示一根内存条,不能组成双通道
    VMware 虚拟机安装win10操作系统系列问题解决
    编译语言和解释语言区别
    SPSS 24下载与安装+授权码
    Reg文件操作
    DLL注册表文件相关内容
    安装TensorFlow失败
    Anaconda 包管理与环境管理
    Cookie设置域名问题,cookie跨域
    准备篇(二)C语言
  • 原文地址:https://www.cnblogs.com/HenryHuang-Never-Settle/p/solution-CF521E.html
Copyright © 2020-2023  润新知