无向图强连通分量缩点+DFS序 codeforces555E Case of Computer Network

来源:互联网 发布:java 多线程 线程池 编辑:程序博客网 时间:2024/06/03 16:29

传送门:点击打开链接

题意:n个点,m条边的无向图,点不一定都连通,有q个查询,每个查询有u和v。现在要把m条边从无向边变成有向边,并要求每个查询的u能通过后来的有向边到达v。问是否存在这样的构造。所有数都<=2e5

思路:这道题写起来太爽了!

首先我们很容易想到通过无向图强连通分量缩点,缩点完后就只剩下了一棵树(或者森林)。

我们接下来考虑不合法的情况,绝对有一节点会满足这个要求:对于节点rt,u是rt子树里的一个节点,u有查询必须要连接到v,而v在rt的子树外。这说明rt所对应的上一条边的边方向已经确定了,但是如果此时在rt的子树外有一个点必须要连一条边到rt的子树里,那么就与前面矛盾了,此时就无答案。

所以我们先通过DFS序给树编号,这样对于一个节点,它的子树中的节点新编号都会在一个连续的区间内。

之后我们只需要维护最大值和最小值,看是否在子树对应的区间外,我们就能知道是否有不满足题意的情况了(噫,语文不是很好,直接看代码我维护的是什么内容把。。

因为可能是森林,所以DFS序编号和后来查询是否满足答案的时候也都要注意是否把所有的通块都遍历完了。

#include <map>#include <set>#include <cmath>#include <ctime>#include <stack>#include <queue>#include <cstdio>#include <cctype>#include <string>#include <vector>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>#include <functional>#define fuck(x) cout<<"["<<x<<"]"#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;typedef pair<int, int> PII;const int MX = 2e5 + 5;int Head[MX], erear;struct Edge {    int u, v, nxt;} E[MX << 1];void edge_init() {    erear = 0;    memset(Head, -1, sizeof(Head));}void edge_add(int u, int v) {    E[erear].u = u;    E[erear].v = v;    E[erear].nxt = Head[u];    Head[u] = erear++;}int n, m, q;int DFN[MX], Low[MX], dsz, tim;int Stack[MX], inStack[MX], Belong[MX], bsz, ssz;int MIN[MX][2], MAX[MX][2], L[MX], R[MX];void DFS_1(int u, int f) {    L[u] = ++dsz;    MIN[u][0] = MIN[u][1] = dsz;    MAX[u][0] = MAX[u][1] = dsz;    for(int i = Head[u]; ~i; i = E[i].nxt) {        int v = E[i].v;        if(v == f) continue;        DFS_1(v, u);    }    R[u] = dsz;}bool DFS_2(int u, int f) {    DFN[u] = 1;    for(int i = Head[u]; ~i; i = E[i].nxt) {        int v = E[i].v;        if(v == f) continue;        if(!DFS_2(v, u)) return false;        MIN[u][0] = min(MIN[u][0], MIN[v][0]);        MAX[u][0] = max(MAX[u][0], MAX[v][0]);        MIN[u][1] = min(MIN[u][1], MIN[v][1]);        MAX[u][1] = max(MAX[u][1], MAX[v][1]);    }    bool a = (MIN[u][0] < L[u] || MAX[u][0] > R[u]);    bool b = (MIN[u][1] < L[u] || MAX[u][1] > R[u]);    if(a && b) return false;    return true;}void trajan(int u, int e) {    inStack[u] = 1;    Stack[++ssz] = u;    DFN[u] = Low[u] = ++dsz;    for(int i = Head[u]; ~i; i = E[i].nxt) {        int v = E[i].v;        if((i ^ 1) == e) continue;        if(!DFN[v]) {            trajan(v, i);            Low[u] = min(Low[u], Low[v]);        } else if(inStack[v]) {            Low[u] = min(Low[u], Low[v]);        }    }    if(DFN[u] == Low[u]) {        bsz++; int v;        do {            v = Stack[ssz--];            inStack[v] = 0;            Belong[v] = bsz;        } while(ssz && v != u);    }}void tarjan_solve(int n) {    dsz = bsz = ssz = 0;    memset(DFN, 0, sizeof(DFN));    for(int i = 1; i <= n; i++) {        if(!DFN[i]) trajan(i, -1);    }    edge_init();    for(int i = 0; i < 2 * m; i += 2) {        int u = E[i].u, v = E[i].v;        u = Belong[u]; v = Belong[v];        if(u == v) continue;        edge_add(u, v);        edge_add(v, u);    }}int main() {    edge_init(); //FIN;    scanf("%d%d%d", &n, &m, &q);    for(int i = 1; i <= m; i++) {        int u, v;        scanf("%d%d", &u, &v);        edge_add(u, v);        edge_add(v, u);    }    tarjan_solve(n);    dsz = 0;    for(int i = 1; i <= bsz; i++) {        DFN[i] = 0;        if(!L[i]) DFS_1(i, -1);    }    bool ans = true;    for(int i = 1; i <= q; i++) {        int u, v;        scanf("%d%d", &u, &v);        u = Belong[u]; v = Belong[v];        MIN[u][0] = min(MIN[u][0], L[v]);        MAX[u][0] = max(MAX[u][0], L[v]);        MIN[v][1] = min(MIN[v][1], L[u]);        MAX[v][1] = max(MAX[v][1], L[u]);    }    for(int i = 1; i <= bsz; i++) {        if(!DFN[i] && !DFS_2(i, -1)) ans = false;    }    printf("%s\n",  ans ? "Yes" : "No");    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 晚上睡觉不安神怎么办 晚上经常睡不着觉怎么办 老是睡不着觉怎么办啊 小孩睡觉不安稳怎么办 睡觉时动不了怎么办 特别累还睡不着怎么办 又累又睡不着怎么办 干活累的睡不着怎么办 狗一有动静就叫怎么办 楼上天天闹动静怎么办 喝了奶茶失眠怎么办 失眠一宿第二天怎么办 睡觉外面噪音大怎么办 怀孕早期晚上睡不着怎么办 短发发尾翘怎么办 很累就是睡不着怎么办 人累但是睡不着怎么办 如果晚上睡不着该怎么办 晚上睡不着觉该怎么办 晚上睡不着该怎么办呢 晚上失眠睡不着该怎么办 晚上一直睡不着该怎么办 怀孕晚上睡不着该怎么办 运动太累睡不着怎么办 运动完睡不着觉怎么办 晚上冷得睡不着怎么办 晚上脚冷睡不着怎么办 短发头发有点乱怎么办 不想让别人睡觉怎么办 15岁晚上睡不着怎么办 16岁青少年失眠怎么办 好累又睡不着怎么办 造口患者拉肚子怎么办? 起床后头发乱怎么办 新生儿睡觉偏头怎么办 婴儿睡觉偏头怎么办 月经期间血下不来怎么办 月经下不来怎么办一点点咖啡色 突然早睡睡不着怎么办 移植后睡不着觉怎么办 孕期喜欢右侧睡怎么办