2017西安网赛一个题
来源:互联网 发布:关键词优化简易 编辑:程序博客网 时间:2024/04/28 13:34
题意给你一个图,然后问你,加入多少条边,能使这个图构成成一个强连通分量
题解主要是我不会强连通分量,后来学了一把,然后这个题就很好解决了,首先,把强连通分量缩成一个点,然后现在就成了一个dag,这个dag中,有入度,有出度的点,没有用,看只有入度,和只有出度的点。取个max就好了
//有向图强连通分量:分量中任何两点均可通过路径互达,缩点后成为一个DAG#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <stack>#include <vector>#include <map>#include <algorithm>using namespace std;const int MaxN = 50000, MaxM = 200000;int T, n, m, all, Timetot, Scctot; int pre[MaxM + 5], last[MaxN + 5], other[MaxM + 5];int pr[MaxM + 5], las[MaxN + 5], oth[MaxM + 5];int dfn[MaxN + 5], low[MaxN + 5], col[MaxN + 5];int ind[MaxN + 5], oud[MaxN + 5];bool usedind[MaxN + 5], usedoud[MaxN + 5], usedused[MaxN + 5];stack <int> sta;vector <int> Scc[MaxN + 5];map <pair<int, int>, bool> used;void Build(int x, int y){ pre[++all] = last[x]; last[x] = all; other[all] = y;}void Init(){ all = -1; memset(last, -1, sizeof(last)); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); Build(u, v); }}void Dfs_Scc(int x, int fa){ dfn[x] = low[x] = ++Timetot; sta.push(x); //强连通分量 存点不存边 int ed = last[x], dr; while (ed != -1) { dr = other[ed]; if (!dfn[dr]) { Dfs_Scc(dr, x); low[x] = min(low[x], low[dr]); } else if (!col[dr] && dfn[dr] < dfn[x]) { low[x] = min(low[x], dfn[dr]); } ed = pre[ed]; } if (low[x] >= dfn[x]) { //强连通分量注意是while出来以后判 Scc[++Scctot].clear(); while (true) { int u = sta.top(); sta.pop(); col[u] = Scctot; Scc[Scctot].push_back(u); if (u == x) break; } }}void rBuild(int x, int y){ pr[++all] = las[x]; las[x] = all; oth[all] = y; ind[x]++; oud[y]++;}void ReBuildGraph(){ used.clear(); all = -1; memset(las, -1, sizeof(las)); //all用原来的,las也记得清成-1 for (int i = 1; i <= n; i++) { int ed = last[i], dr; while (ed != -1) { dr = other[ed]; if (col[i] != col[dr] && !used[make_pair(col[i], col[dr])]) { used[make_pair(col[i], col[dr])] = true; rBuild(col[i], col[dr]); } ed = pre[ed]; } }}void Solve(){ Timetot = Scctot = 0; memset(dfn, 0, sizeof(dfn)); //dfn, low每次必须清空 memset(low, 0, sizeof(low)); memset(col, 0, sizeof(col)); memset(ind, 0, sizeof(ind)); memset(oud, 0, sizeof(oud)); for (int i = 1; i <= n; i++) if (!dfn[i]) Dfs_Scc(i, -1); ReBuildGraph(); memset(usedused, 0, sizeof(usedused)); int num = 0; for (int i = 1; i <= n; i++) { if (!usedused[col[i]]) { usedused[col[i]] = true; num++; } } memset(usedind, 0, sizeof(usedind)); memset(usedoud, 0, sizeof(usedoud)); int sum_ind = 0, sum_oud = 0; for (int i = 1; i <= n; i++) { if (ind[col[i]] == 0 && !usedind[col[i]]) { usedind[col[i]] = true; sum_ind++; } if (oud[col[i]] == 0 && !usedoud[col[i]]) { usedoud[col[i]] = true; sum_oud++; } } if (num == 1) printf("0\n"); else printf("%d\n", max(sum_ind, sum_oud));}int main(){ scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { Init(); Solve(); } return 0;}
阅读全文
0 0
- 2017西安网赛一个题
- HDU5009西安网赛2014
- 2017西安网络赛C_SUM
- 2017西安网络赛B_Coin
- 西安网络赛e题
- hdu5007 ACM-ICPC 西安赛区网赛A题 水题
- 2017 ACM西安网络赛 E题 Maximum Flow
- 2017 ACM西安网络赛 G题 Xor
- 2017西安网络赛G题 分类暴力
- 2017西安区域赛现场赛
- hdu5015(2014西安网赛) 233 Matrix
- 2017亚洲区域赛-西安赛区
- Coin 2017ICPC西安网络赛
- 【2017西安网络赛】E Maximum Flow
- 【2017西安网络赛】C Sum
- 2017西安ICPC区域赛小结
- hdu5008 西安赛区网络赛 B题
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛b题Coin(矩阵快速幂)
- PAT 1010. Radix (25) 变态题,各种坑点
- git常用命令整理
- Longest Commen Prefix
- 代码笔记摘要
- cookie
- 2017西安网赛一个题
- 爬虫-03-XPath & CSS
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B. Coin
- 2017.09.16 python第18次笔记
- Calico 的网络结构是什么?- 每天5分钟玩转 Docker 容器技术(68)
- lunix下跑caffe用到的一些命令
- 35 个 Java 代码性能优化总结
- Android 自定义 SeekBar
- JSON语法