CF555E Case of Computer Network

题面:https://www.luogu.com.cn/problem/CF555E
题意:给定一张\(n\)个点\(m\)条边的无向图。
给定\(q\)组有向点对\((s,t)\)
询问是否存在使得所有\(s\)都能到达\(t\)的无向图中每条边的定向方案。
n,m,q \(\leq\) 2e5
题解:
看到这种关于无向图连通性的问题,我们可以想到边双。
如果两点在边双中,我们可以将边双里的边定向为一些环,
这样这些点一定是可以到达的。
考虑边双缩点,将整张图缩成一个森林。
接下来,对于每对\((s,t)\),我们树上差分记录一下
每条边的方向,最后DFS判断一下就行了。
时间复杂度\(O(n+m)\)
代码:

#include
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define STS system("pause")
templateI read(D &res){
    res=0;register D g=1;register char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')g=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        res=(res<<3)+(res<<1)+(ch^48);
        ch=getchar();
    }
    res*=g;
}
struct E{
    int to,nt;
}e[404000];
#define T e[k].to
int n,m,Q,tot,X,Y,sn,head[202000];
int dfn[202000],low[202000],clr[202000],color,mill,vis[202000];
int dep[202000],fa[202000],f[202000][20],lg[202000],top[202000];
int up[202000],down[202000];
stacks;
vectorv[202000];
vector::iterator it;
I tarjan(int x,int pre){
    dfn[x]=low[x]=++mill;
    s.push(x);vis[x]=1;
    for(re k=head[x];k!=-1;k=e[k].nt){
        if(k==(pre^1))continue;
        if(!dfn[T]){
            tarjan(T,k);
            low[x]=min(low[x],low[T]);
        }
        else if(vis[T])low[x]=min(low[x],dfn[T]);
    }
    if(dfn[x]==low[x]){
        ++color;
        while(s.top()!=x){clr[s.top()]=color;vis[s.top()]=0;s.pop();}
        clr[x]=color;vis[x]=0;s.pop();
    }
}
I D_1(int x,int fat,int depth,int topi){
    //cout<>i)&1)x=f[x][i];
    }
    if(x==y)return x;
    FOR(i,lg[dep[x]],0){
        if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
I D_3(int x,int fat){
    if(!sn)return;
    for(auto k:v[x]){
        if(k==fat)continue;
        D_3(k,x);
        if(!sn)return;
        up[x]+=up[k];down[x]+=down[k];
    }
    //cout<>1]+1,top[i]=i;
    F(i,1,color){
        sort(v[i].begin(),v[i].end());
        it=unique(v[i].begin(),v[i].end());
        v[i].erase(it,v[i].end());
        //cout<

你可能感兴趣的:(CF555E Case of Computer Network)