Cycling City CF521E

Cycling City

毒瘤题

首先建dfs树,由于是个无向图所有返祖边都是连向祖先的。

判是否有解其实很简单,只要图不是一个仙人掌就有解了。

仙人掌有关可以看这个博客

但是这道题由于要输出路径成功变成了一个一个顶俩的题。。。。。

通过判仙人掌我们确认了一个点,它连向自己父亲的路径至少被两个边所覆盖。

然后我们可以从这个点开始深搜,找到这两个返祖,注意是返向这个点祖先的路径。

于是有起点就是这两个路径下端的lca,终点就是这两个路径上端点最深的一个(画图很好看出来的)

然后有哪些路径就显然了。。

输出方案毒瘤!

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
#define MAXN 201116
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
int n , m;
vector<int> G[MAXN];
int dep[MAXN] , par[MAXN] , dir[MAXN];
void dfs( int u , int fa ) {
	dep[u] = dep[fa] + 1 , par[u] = fa;
	for( int i = 0 ; i < G[u].size( ) ; ++ i ) {
		int v = G[u][i];
		if( v == fa ) continue;
		if( !dep[v] ) dfs( v , u ) , dir[u] += dir[v];
		else if( dep[v] < dep[u] )
			++ dir[u] , -- dir[ v ];
	}
}
int l , r , L , R;
int s;
void dfs2( int u , int fa ) {
	for( int i = 0 ; i < G[u].size() ; ++ i ) {
		int v = G[u][i];
		if( dep[v] == dep[u] + 1 ) dfs2( v , u );
		else if( dep[v] < dep[s] && v != fa ) {
			if( l ) L = u , R = v;
			else l = u , r = v;
		}
		if( L ) return;
	}
}
vector<int> ans , tmp;
void doit( int fr , int to ) {
	if( dep[fr] < dep[to] ) {
		tmp.clear();
		to = par[to];
		while( to != fr ) 
			tmp.pb( to ) , to = par[to];
		tmp.pb( fr );
		for( auto it = tmp.rbegin() ; it != tmp.rend( ) ; ++ it )
			ans.pb( *it );
		return;
	}
	while( fr != to ) 
		ans.pb( fr ) , fr = par[fr];
}
int main() {
	cin >> n >> m;
	for( int i = 1 , u , v ; i <= m ; ++ i ) {
		scanf("%d%d",&u,&v);
		G[u].pb( v ) , G[v].pb( u );
	}
	for( int i = 1 ; i <= n ; ++ i ) if( !dep[i] ) dfs( i , 0 );
	for( int i = 1 ; i <= n ; ++ i ) if( dir[i] > 1 ) 
		{ s = i; break; }
	if( !s ) return puts("NO") , 0;
	puts("YES");
	dfs2( s , par[s] );
	if( dep[R] < dep[r] ) swap( r , R ) , swap( l , L );
	int x = l , y = L;
	while( x != y ) dep[x] > dep[y] ? x = par[x] : y = par[y];
	
	doit( x , l ) , ans.pb( l ) , doit( r , R ) , ans.pb( R );
	printf("%d ",ans.size());
	for( auto& x : ans ) printf("%d ",x);
	puts("");
	
	ans.clear();
	doit( x , L ) , ans.pb( L ) , ans.pb( R );
	printf("%d ",ans.size());
	for( auto& x : ans ) printf("%d ",x);
	puts("");
	
	ans.clear();
	doit( x , R ) , ans.pb( R );
	printf("%d ",ans.size());
	for( auto& x : ans ) printf("%d ",x);
	puts("");
	
}
posted @ 2019-10-11 06:57  yijan  阅读(312)  评论(0编辑  收藏  举报