zoukankan      html  css  js  c++  java
  • day48-安博施

    T1 CF555E Case of Computer Network

    给定一张 n 个点 m 条边的无向图。
    给定 q 组有向点对(s,t)。
    询问是否存在使得所有 s 都能到达 t 的无向图中每条边的定向方案。
    (n,m,q le 2 imes 10^5)

    solution

    其实吧,这题没有想象中那么难。

    (Tarjan) 求割边,缩点,然后得到一棵树。

    对于一个询问((u , v))

    若u,v在同一个边双中一定存在一种方法使得这个边双的中的点两两互达,(边双中有环嘛。。)

    若不在一个联通块里,(不在一棵树里),那么肯定无解。

    若都在一个树上就,将这条路劲上的边都打上一个标记,即可,具体实现可以用树上差分的方法。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5+10;
    inline int read()
    {
    	register int x = 0 , f = 0; register char c = getchar();
    	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
    	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48) , c = getchar();
    	return f ? -x : x;
    }
    int n , m , q , cnt = 1 , dfn_id , col_id , tag_id;
    int head[N] , dfn[N] , vis[N << 1] , low[N] , col[N] , tag[N] , d[N] , s1[N] , s2[N] , f[N][20];
    vector<int> G[N];
    struct edge { int v , nex; }e[N << 1];
    inline void add(int u , int v) { e[++cnt].v = v; e[cnt].nex = head[u]; head[u] = cnt; }
    
    void Tarjan(int x , int f)
    {
    	dfn[x] = low[x] = ++dfn_id;
    	for(int i = head[x] , v; i ; i = e[i].nex) if(i != f)
    	{
    		v = e[i].v;
    		if(!dfn[v]) 
    		{
    			Tarjan(v , i ^ 1) , low[x] = min(low[x] , low[v]);
    			if(low[v] > dfn[x]) vis[i] = vis[i ^ 1] = 1;
    		}
    		else low[x] = min(low[x] , dfn[v]);
    	}
    }
    
    void dfs1(int x)
    {
    	col[x] = col_id;
    	for(int i = head[x] ; i ; i = e[i].nex) if(!col[e[i].v] && !vis[i]) dfs1(e[i].v);
    }
    
    void dfs2(int x)
    {
    	tag[x] = tag_id;
    	for(auto v : G[x]) if(v != f[x][0]) 
    	{
    		f[v][0] = x; d[v] = d[x] + 1;
    		for(int i = 1 ; i < 20 ; ++i) f[v][i] = f[f[v][i-1]][i-1];
    		dfs2(v);
    	}
    }
    
    int LCA(int x , int y)
    {
    	if(d[x] < d[y]) swap(x , y);
    	for(int i = 19 ; ~i ; --i) if(d[f[x][i]] >= d[y]) x = f[x][i];
    	if(x == y) return x;
    	for(int i = 19 ; ~i ; --i) if(f[x][i] != f[y][i]) x = f[x][i] , y = f[y][i];
    	return f[x][0];
    }
    
    bool check(int x)
    {
    	for(auto v : G[x]) if(v != f[x][0])
    	{
    		if(!check(v) || (s1[v] && s2[v])) return false;
    		s1[x] += s1[v]; s2[x] += s2[v];
    	}
    	return true;
    }
    
    int main()
    {
    	n = read(); m = read(); q = read();
    	for(int i = 1 , u , v; i <= m ; ++i) u = read() , v = read() , add(u , v) , add(v , u);
    	for(int i = 1 ; i <= n ; ++i) if(!dfn[i]) Tarjan(i , -1);
    	for(int i = 1 ; i <= n ; ++i) if(!col[i]) col_id++ , dfs1(i);
    	for(int i = 1 ; i <= n ; ++i) for(int j = head[i] ; j ; j = e[j].nex) if(col[i] < col[e[j].v]) G[col[i]].push_back(col[e[j].v]) , G[col[e[j].v]].push_back(col[i]);
    	for(int i = 1 ; i <= col_id ; ++i) if(!tag[i]) tag_id++ , d[i] = 1 , dfs2(i);
    	for(int i = 1 , u , v ; i <= q ; ++i)
    	{
    		u = read(); v = read(); u = col[u]; v = col[v]; if(u == v) continue;
    		if(tag[u] != tag[v]) return puts("No") , 0;
    		int p = LCA(u , v);
    		s1[u]++; s1[p]--; s2[v]++; s2[p]--;
    	}
    	for(int i = 1 ; i <= col_id ; ++i) if(d[i] == 1 && !check(i)) return puts("No") , 0;
    	puts("Yes");
    	return 0;	
    }
    
  • 相关阅读:
    课程作业3
    课程作业一(改进)
    C语言中的几种常见排序算法
    PADS 导Gerber文件
    时钟信号线上串一小电阻的作用
    Allegro pcb -等长设计
    Allegro PCB -内层分割,比如电源层需要分割几种电源
    Allegro PCB -通孔焊盘制作 及Flash制作
    Allegro PCB -如何做自定义焊盘
    MFC中的NMHDR结构体和NMUPDOWN结构体
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/13139745.html
Copyright © 2011-2022 走看看