zoukankan      html  css  js  c++  java
  • #边双缩点,并查集#洛谷 2416 泡芙

    题目

    给出一张 (n) 个点,(m) 条边的无向图,边权为0或1,
    问是否存在一条每条边最多经过一次的路径中至少有一条边的边权为1,
    多组数据给出起点和终点


    分析

    考虑在一个边双中只要有边权为1的边,那么这个边双就是合法的,
    那么跑一遍Tarjan之后,给边双缩点,
    不存在当且仅当起点和终点所在边双不合法且路径上(桥)边权全为0,
    那么将桥边权为0的用并查集缩成连通块,如果连通那么边权全为0


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=300011; struct node{int y,w,next;}e[N<<1];
    int dfn[N],low[N],f[N],bridge[N<<1],et=1,n,w[N],tot,as[N],col[N],cnt;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed min(int x,int y){return x<y?x:y;}
    inline signed getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
    inline void tarjan(int x,int F){
    	dfn[x]=low[x]=++tot;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (!dfn[e[i].y]){
    		tarjan(e[i].y,i^1),low[x]=min(low[x],low[e[i].y]);
    		if (dfn[x]<low[e[i].y]) bridge[i]=bridge[i^1]=1;
    	}else if (i!=F) low[x]=min(low[x],dfn[e[i].y]);
    }
    inline void dfs(int x){
    	col[x]=cnt;
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (!col[e[i].y]&&!bridge[i]) dfs(e[i].y);
    }
    inline void Merge(int x,int y){
    	rr int fa=getf(x),fb=getf(y);
    	if (fa==fb) return; f[fa]=fb;
    } 
    signed main(){
    	n=iut();
    	for (rr int m=iut();m;--m){
    		rr int x=iut(),y=iut(),w=iut();
    		e[++et]=(node){y,w,as[x]},as[x]=et;
    		e[++et]=(node){x,w,as[y]},as[y]=et;
    	}
        tarjan(1,0);
        for (rr int i=1;i<=n;++i)
    	    if (!col[i]) ++cnt,dfs(i);
    	for (rr int i=1;i<=cnt;++i) f[i]=i;
        for (rr int i=2;i<=et;i+=2)
    	if (col[e[i^1].y]==col[e[i].y]) w[col[e[i].y]]+=e[i].w;
    	    else if (!e[i].w) Merge(col[e[i^1].y],col[e[i].y]);
    	for (rr int Q=iut();Q;--Q){
    		rr int x=col[iut()],y=col[iut()];
    		if (w[x]||w[y]) puts("YES");
    		else if (getf(x)==getf(y)) puts("NO");
    		    else puts("YES");
    	}
    	return 0;
    }
    
  • 相关阅读:
    正则表达式
    Java 枚举(enum) 详解7种常见的用法
    【20170921】(Unfinished)2017暑假北京学习 day 2
    (Unfinished)2017暑假北京学习 day 2
    Openjudge NOI题库 数论4975 两只鼹鼠
    Openjudge NOI题库 数论185 反正切函数的应用
    Noip1998 提高组3 卢斯加法表
    【自己的小玩具程序】化学方程式配平【测试中】【未完成】
    Code Vs 1010 过河卒
    NOI 练手题 图像旋转翻转变换
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15149526.html
Copyright © 2011-2022 走看看