无向图强连通分量缩点+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
- 无向图强连通分量缩点+DFS序 codeforces555E Case of Computer Network
- 缩点+树上差分——Codeforces555E Case of Computer Network
- POJ 1236 Network of Schools强连通分量缩点
- POJ 1236 Network of Schools (强连通分量+缩点)
- POJ 1236 Network of Schools 强连通分量+缩点
- poj 1236 Network of Schools (强连通分量+缩点)
- poj 1236 Network of Schools(强连通分量+缩点)
- poj 1236 Network of Schools(强连通分量缩点)
- POJ-1236-Network of Schools【强连通分量】【缩点】
- POJ1236 Network of Schools(缩点+结论+强连通分量)
- POJ 1236 Network of Schools(强连通分量,缩点)
- 【连通图|强连通分量+缩点】POJ-1236 Network of Schools
- HDU 4612 Warm up(无向图强连通分量缩点建树)
- HDU4612-Warm up(无向图强连通分量缩点)
- sdut 3262 Circle of Friends (SCC缩点) 有向图 强连通分量模板
- 无向图dfs求连通分量
- poj2676 有向图强连通分量+缩点
- POJ 1236 Network of Schools【强连通分量分解&&缩点||tarjan&&缩点】
- Stopwatch 类
- 两步搞定 Tomcat 下启用 https:// 访问
- java中HashMap详解
- jersey_No WebApplication provider is present
- 奇葩的非理性
- 无向图强连通分量缩点+DFS序 codeforces555E Case of Computer Network
- 得到缓存及清理缓存
- EXCEL宏函数汇总
- adaboost python 实例
- PostgreSQL中删除的数据能否恢复
- SFilter框架理解
- [POJ 3684] Physics Experiment (脑洞+弹性碰撞模型)
- C#在终端服务器只允许运行应用程序的一个实例
- ElasticSearch的Marvel更新license