HDU 3861 The King’s Problem 强联通缩点 + 最小路径覆盖
来源:互联网 发布:淘宝市场行情有用吗 编辑:程序博客网 时间:2024/05/04 00:08
题意:给你一个有向图,有一些规则:
1:对于两个点u v,如果存在u到v的路径并且存在v到u的路径,则他们属于同一个阵营
2:对于两个点u v,如果存在u到v的路径或者存在v到u的路径,则他们可以属于同一个阵营
3:每个点只能属于一个阵营
问你这个有向图最少能分为几个阵营
思路:首先强联通缩点,对于第二条规则,其实也就是说找一条路径使得其覆盖尽量多的点,用二分图解决即可。
这题不能用邻接矩阵,会MLE。。
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define REP( i, a, b ) for( int i = a; i < b; i++ )#define CLR( a , x ) memset( a , x , sizeof a )const int maxn = 5000 + 10;const int maxe = 100000 + 10;struct Edge{ int v, next; Edge (int v = 0, int next = 0) : v(v), next(next) {}};struct SCC{ int Head[maxn], cntE; int dfn[maxn], low[maxn], dfs_clock; int scc[maxn], scc_cnt; int Stack[maxn], top; bool ins[maxn]; Edge edge[maxe]; void init(){ top = 0; cntE = 0; scc_cnt = 0; dfs_clock = 0; CLR(ins, 0); CLR(dfn, 0); CLR(Head, -1); } void add(int u, int v){ edge[cntE] = Edge(v, Head[u]); Head[u] = cntE++; } void Tarjan(int u){ dfn[u] = low[u] = ++dfs_clock; Stack[top++] = u; ins[u] = 1; for (int i = Head[u] ; ~i ; i = edge[i].next){ int v = edge[i].v; if (!dfn[v]){ Tarjan (v) ; low[u] = min(low[u], low[v]) ; } else if (ins[v]) low[u] = min (low[u], dfn[v]) ; } if (low[u] == dfn[u]){ ++scc_cnt; while ( 1 ){ int v = Stack[--top]; ins[v] = 0; scc[v] = scc_cnt; if (v == u) break; } } } void find_scc(int n){ REP(i, 0, n) if(!dfn[i]) Tarjan (i) ; }}scc;int X, Y;int linker[maxn];bool vis[maxn];Edge e[maxe];int cnte, H[maxn];void Init(){ memset(H, -1, sizeof(H)); cnte = 0;}void Add(int u, int v){ e[cnte] = Edge(v, H[u]); H[u] = cnte++;}bool dfs(int u){ for(int i = H[u]; ~i; i = e[i].next)if(!vis[e[i].v]){ vis[e[i].v] = true; if(linker[e[i].v] == -1 || dfs(linker[e[i].v])){ linker[e[i].v] = u; return true; } } return false;}int hungary(){ int ans = 0; memset(linker, -1, sizeof(linker)); for(int u = 0; u < X; u++){ memset(vis, false, sizeof(vis)); if(dfs(u)) ans++; } return ans;}void solve(){ int n, m; scanf("%d%d", &n, &m); scc.init(); for(int i = 0; i < m; i++){ int u, v; scanf("%d%d", &u, &v); --u; --v; scc.add(u, v); } scc.find_scc(n); Init(); X = Y = scc.scc_cnt; for(int i = 0; i < n; i++) for(int j = scc.Head[i]; ~j; j = scc.edge[j].next){ int u = i, v = scc.edge[j].v; if(scc.scc[u] != scc.scc[v]){ Add(scc.scc[u] - 1, scc.scc[v] - 1); } } printf("%d\n", scc.scc_cnt - hungary());}int main(){ int T; scanf("%d", &T); while(T--) solve(); return 0;}
0 0
- HDU 3861 The King’s Problem 强联通缩点 + 最小路径覆盖
- HDU --- 3861 The King’s Problem 【强联通缩点 + 最小路径覆盖】
- HDOJ 3861 - The King’s Problem tarjan求强联通分量&缩点&有向图最小路径覆盖(匈牙利)
- 【HDU】3861 The King’s Problem 强连通缩点+有向图最小路径覆盖
- The King’s Problem (hdu 3861 强连通缩点+最小路径覆盖)
- HDU 3861 The King’s Problem(强连通缩点 + 最小路径覆盖)
- HDU 3861 The King’s Problem 强连通缩点+最小路径覆盖
- hdu 1269 The King’s Problem(强连通分量+缩点+最小路径覆盖)
- HDU 3861 The King’s Problem (强连通分量缩点+二分图匹配最小路径覆盖)
- hdu 3861 The King’s Problem(缩点+最小路径覆盖)
- hdu 3861 The King's problem(SCC缩点+最小路径覆盖)
- HDU 3861--The King’s Problem【scc缩点构图 && 二分匹配求最小路径覆盖】
- hdu 3861 The King’s Problem tarjan+缩点+最小路径覆盖
- HDU 3861 The King’s Problem(tarjan缩点+最小路径覆盖ISAP)
- HDU 3861 The King’s Problem 强连通+最小路径覆盖
- hdu 3861 The King’s Problem (强连通+最小路径覆盖)
- HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)
- HDU - 3861 The King’s Problem(强连通分量+最小路径覆盖)
- Android greenDao 数据库的使用(三)
- 006redis的string类型
- freemark生成静态页面
- 【一】 Chrome的多线程模型
- android程序员简历模板
- HDU 3861 The King’s Problem 强联通缩点 + 最小路径覆盖
- mysql编码
- 标准模板库(三):STL里面的算法介绍
- 水晶报表分页汇总小计
- ngx.md5生成文件的md5值
- 使用pdsh、ClusterSSH和mussh管理集群系统
- 007redis的hash类型
- HDU 1846 Brave Game(巴什博奕)
- SAE WordPress添加favicon.ico