• codeforces #310 div1 E


    算得上是比较水的E题了吧,自己想了想写了写居然1A了

    对于这道题,我们很容易想到对于原图的一个边双,定向后任意两点间一定可达

    那么我们可以求出原图的边双并将每个边双缩成一个点

    那么原图就变成了无环的无向图,也就是一片森林

    之后我们考虑每个任务:

    1、如果S和T处于一个边双里,显然是可行的

    2、如果S和T处于两棵树中,显然不连通不可行

    3、S和T处于一棵树中,那么S->lca的所有边都是向上的,lca->T的所有边的都是向下的

    对于第三种情况,我们可以在S上打一个up标记,在T上打一个down标记

    之后在lca上将传递过来的up和down清除即可

    那么最后我们只需要对森林做一遍DFS即可判断可行性

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<stack>
    using namespace std;
    
    const int maxn=200010;
    int n,m,q;
    int u,v;
    struct Edge{
    	int u,v;
    }c[maxn];
    int h[maxn],cnt=1;
    struct edge{
    	int to,next;
    }G[maxn<<2];
    int pre[maxn],low[maxn];
    int dfs_clock=0,bcc_cnt=0;
    int bccno[maxn],f[maxn];
    int fa[maxn],anc[maxn][20];
    int dep[maxn];
    int up[maxn],down[maxn];
    stack<int>S;
    
    int ufs(int x){return f[x]==x?x:f[x]=ufs(f[x]);}
    void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
    void DFS(int u,int f){
    	pre[u]=low[u]=++dfs_clock;S.push(u);
    	for(int i=h[u];i;i=G[i].next){
    		if(i==(f^1))continue;
    		int v=G[i].to;
    		if(!pre[v]){
    			DFS(v,i);
    			low[u]=min(low[u],low[v]);
    		}else if(!bccno[v])low[u]=min(low[u],pre[v]);
    	}
    	if(low[u]==pre[u]){
    		bcc_cnt++;
    		for(;;){
    			int now=S.top();S.pop();
    			bccno[now]=bcc_cnt;
    			if(now==u)break;
    		}
    	}return;
    }
    void Get_Tree(){
    	for(int i=1;i<=n;++i){
    		if(!pre[i])DFS(i,0);
    	}return;
    }
    void Get_DFS(int u,int f){
    	fa[u]=f;
    	for(int i=h[u];i;i=G[i].next){
    		int v=G[i].to;
    		if(v==f)continue;
    		dep[v]=dep[u]+1;
    		Get_DFS(v,u);
    	}return;
    }
    void pre_LCA(){
    	for(int i=1;i<=n;++i){
    		anc[i][0]=fa[i];
    		for(int j=1;(1<<j)<=n;++j)anc[i][j]=-1;
    	}
    	for(int j=1;(1<<j)<=n;++j){
    		for(int i=1;i<=n;++i){
    			if(anc[i][j-1]!=-1){
    				int a=anc[i][j-1];
    				anc[i][j]=anc[a][j-1];
    			}
    		}
    	}return;
    }
    int LCA(int p,int q){
    	if(dep[p]<dep[q])swap(p,q);
    	int log;
    	for(log=0;(1<<log)<=dep[p];++log);log--;
    	for(int i=log;i>=0;--i){
    		if(dep[p]-(1<<i)>=dep[q])p=anc[p][i];
    	}
    	if(p==q)return p;
    	for(int i=log;i>=0;--i){
    		if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){
    			p=anc[p][i];q=anc[q][i];
    		}
    	}return fa[p];
    }
    void check(int u,int f){
    	for(int i=h[u];i;i=G[i].next){
    		int v=G[i].to;
    		if(v==f)continue;
    		check(v,u);
    		up[u]+=up[v];down[u]+=down[v];
    	}
    	if(up[u]>0&&down[u]>0){
    		printf("No
    ");
    		exit(0);
    	}return;
    }
    
    int main(){
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=m;++i){
    		scanf("%d%d",&c[i].u,&c[i].v);
    		add(c[i].u,c[i].v);add(c[i].v,c[i].u);
    	}
    	Get_Tree();
    	memset(h,0,sizeof(h));cnt=1;
    	for(int i=1;i<=n;++i)f[i]=i;
    	for(int i=1;i<=m;++i){
    		int a=bccno[c[i].u];
    		int b=bccno[c[i].v];
    		if(a!=b){
    			add(a,b);add(b,a);
    			int d1=ufs(a),d2=ufs(b);
    			if(d1!=d2)f[d1]=d2;
    		}
    	}
    	for(int i=1;i<=bcc_cnt;++i){
    		int rt=ufs(i);
    		if(rt==i)Get_DFS(rt,-1);
    	}
    	pre_LCA();
    	for(int i=1;i<=q;++i){
    		scanf("%d%d",&u,&v);
    		int a=bccno[u],b=bccno[v];
    		if(ufs(a)!=ufs(b)){printf("No
    ");return 0;}
    		int lca=LCA(a,b);
    		up[a]++;down[b]++;up[lca]--;down[lca]--;
    	}
    	for(int i=1;i<=bcc_cnt;++i){
    		int rt=ufs(i);
    		if(rt==i)check(rt,-1);
    	}printf("Yes
    ");return 0;
    }
    

      

  • 相关阅读:
    2016.5.15——leetcode:Number of 1 Bits ,
    2016.5.14——leetcode-HappyNumber,House Robber
    记录学习过程
    npm 模块安装机制简介
    搭建Vue.js开发环境(window10)
    pwd 显示当前所在的工作路径
    Lucene 6.5.0 入门Demo
    java.lang.UnsupportedClassVersionError
    window.onload 和 $(document).ready(function(){}) 的区别
    plsql + 客户端 连接oracle数据库
  • 原文地址:https://www.cnblogs.com/joyouth/p/5369181.html
Copyright © 2020-2023  润新知