zoukankan      html  css  js  c++  java
  • 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("");
    	
    }
    
  • 相关阅读:
    寒假补习记录_4
    寒假补习记录_3
    寒假补习记录_2
    寒假补习记录_1
    公文流转系统编程
    Javaweb编程
    转:在静态方法中访问类的实例成员
    Java字段初始化规律
    原码,反码,补码浅谈
    java第二节课课后
  • 原文地址:https://www.cnblogs.com/yijan/p/cf521e.html
Copyright © 2011-2022 走看看