HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)
2017-05-06 16:01
417 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3861
题意:
国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意两个城市u,v,有从u到v的路径或从v到u的路径。求最少可以分成几个州。
思路:
这道题目挺好。
首先,强连通分量进行缩点,重新建图。
新建的图就是一个DAG图,接下来就转换成了最小路径覆盖问题。
最小路径覆盖就是用尽量少的不相交的简单路径覆盖DAG的所有顶点。每个顶点只属于一条路径,单个顶点也可以作为一条路径。
最小路径覆盖=结点总数-最大匹配。
题意:
国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意两个城市u,v,有从u到v的路径或从v到u的路径。求最少可以分成几个州。
思路:
这道题目挺好。
首先,强连通分量进行缩点,重新建图。
新建的图就是一个DAG图,接下来就转换成了最小路径覆盖问题。
最小路径覆盖就是用尽量少的不相交的简单路径覆盖DAG的所有顶点。每个顶点只属于一条路径,单个顶点也可以作为一条路径。
最小路径覆盖=结点总数-最大匹配。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<cmath> #include<stack> using namespace std; const int maxn=5000+5; int n,m; vector<int> G[maxn]; int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; stack<int> S; vector<int> new_G[maxn]; int vis[maxn]; int match[maxn]; void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if(!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]); } if (pre[u] == lowlink[u]) { scc_cnt++; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if (x == u) break; } } } void find_scc(int n) { dfs_clock = scc_cnt = 0; memset(pre, 0, sizeof(pre)); memset(sccno, 0, sizeof(sccno)); for (int i = 1; i <= n; i++) if (!pre[i]) dfs(i); } int match_dfs(int x) { for(int i=0;i<new_G[x].size();i++) { int v=new_G[x][i]; if(!vis[v]) { vis[v]=1; if(match[v]==-1 || match_dfs(match[v])) { match[v]=x; return 1; } } } return 0; } int main() { //freopen("D:\\input.txt","r",stdin); int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) G[i].clear(); while(m--) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); } find_scc(n); for(int i=1;i<=scc_cnt;i++) new_G[i].clear(); for(int u=1;u<=n;u++) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(sccno[u]!=sccno[v]) new_G[sccno[u]].push_back(sccno[v]); } } int tot=0; memset(match,-1,sizeof(match)); for(int i=1;i<=scc_cnt;i++) { memset(vis,0,sizeof(vis)); tot+=match_dfs(i); } printf("%d\n",scc_cnt-tot); } return 0; }
相关文章推荐
- hdu 3861 强连通分量缩点+二分匹配求最小路径覆盖
- HDU 3861 The King’s Problem (强连通分量缩点+二分图匹配最小路径覆盖)
- hdu 3861 (强连通分量+最小路径覆盖)题意有些怪
- HDU 3861 The King’s Problem(强连通缩点 + 最小路径覆盖)
- hdu 3861(缩点+最小路径覆盖)
- 强连通+最小路径覆盖 hdu 3861
- HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)
- HDU 3861 The King’s Problem 强连通分量分解 + 二分图最小路径覆盖
- [HDU 3861] The King's Problem (最小路径覆盖)
- hdu 3861 The King’s Problem【强连通Kosaraju+最小路径覆盖】
- hdu 3861 强量通分量+最小路径覆盖
- 有向图最小路径覆盖方法浅析、证明 //hdu 3861
- HDU 3861--The King’s Problem【scc缩点构图 && 二分匹配求最小路径覆盖】
- hdu-3861(强连通图缩点+二分图最小路径覆盖)
- HDU 3861 强联通分量+最小路径覆盖
- 有向图最小路径覆盖方法浅析、证明 //hdu 3861
- The King’s Problem (hdu 3861 强连通缩点+最小路径覆盖)
- hdu 3861 The King's problem(SCC缩点+最小路径覆盖)
- 【HDU】3861 The King’s Problem 强连通缩点+有向图最小路径覆盖
- hdu 3861(tarjan 缩点 + 二分图匹配 求最小路径覆盖