HDU 3861 The King’s Problem
Posted icode-xiaohu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3861 The King’s Problem相关的知识,希望对你有一定的参考价值。
题意:给我们一个图,问我们最少能把这个图分成几部分,使得每部分内的任意两点都能至少保证单向连通。
思路:使用tarjan算法求强连通分量然后进行缩点,形成一个新图,易知新图中的每个点内部的内部点都能保证双向连通,而新图中的点都是单向无环的,这个时候题目中要求的划分部分的条件,其实就是求最短路径覆盖(需要好好想一想),最短路径覆盖 = 结点个数 - 最大匹配值。
这个题我当时把j写成了i,就这么一个小地方,找了快20分钟,还死活发现不了。。真是晕死了~
#include<iostream> #include<cstdio> #include<stack> #include<cstring> using namespace std; #define maxn 5050 struct EDGE { int to,nxt; } edge[maxn*20]; EDGE newmap[maxn*20]; int head[maxn],low[maxn],dfn[maxn],id[maxn],newhead[maxn]; int vis[maxn],match[maxn]; int tot,sum,tot1; stack <int> s; void init() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(id,0,sizeof(id)); memset(head,-1,sizeof(head)); memset(newhead,-1,sizeof(newhead)); tot = 0,sum = 0; tot1 = 0; while(!s.empty()) s.pop(); } void add_edge(int x,int y) { newmap[tot1].to = y; newmap[tot1].nxt = newhead[x]; newhead[x] = tot1++; } void tarjan(int u) { s.push(u); dfn[u] = low[u] = ++tot; for(int i = head[u]; i != -1; i = edge[i].nxt) { int v = edge[i].to; if(!dfn[v]) { tarjan(v); low[u] = min(low[u],low[v]); } else if(!id[v]) { low[u] = min(low[u],dfn[v]); } } if(low[u] == dfn[u]) { sum++; while(!s.empty()) { int num = s.top(); s.pop(); id[num] = sum; if(num == u) break; } } return; } bool Find(int u) { for(int i = newhead[u]; i != -1;i = newmap[i].nxt) { int v = newmap[i].to; if(!vis[v]) { vis[v] = 1; if(match[v] == -1 || Find(match[v])) { match[v] = u; return true; } } } return false; } int erfen() { int ans = 0; memset(match,-1,sizeof(match)); for(int i = 1;i <= sum;i++) { for(int j = 1;j <= sum;j++) vis[j] = 0; if(Find(i)) ans++; } return ans; } int main() { int t,n,m,x,y; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i = 0; i < m; i++) { scanf("%d%d",&x,&y); edge[i].to = y; edge[i].nxt = head[x]; head[x] = i; } for(int i = 1;i <= n;i++) { if(!dfn[i]) tarjan(i); } for(int i = 1;i <= n;i++) { int u = i; for(int j = head[u];j != -1;j = edge[j].nxt) { int v = edge[j].to; if(id[u] != id[v]) { add_edge(id[u],id[v]); } } } int ans = erfen(); printf("%d\n",sum-ans); } return 0; }
以上是关于HDU 3861 The King’s Problem的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3861.The King’s Problem 强联通分量+最小路径覆盖
hdu 3861 The King’s Problem trajan缩点+二分图匹配
HDU - 3861 The King’s Problem (强连通分量+最小路径覆盖)
HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)