【强连通缩点+二分匹配】 HDOJ 3861 The King’s Problem

来源:互联网 发布:赛程安排软件 编辑:程序博客网 时间:2024/05/05 07:57

题目就是求最小覆盖。。先强连通缩点预处理出DAG图,然后在DAG图上做二分匹配,DAG图的点数-最大匹配就是最小覆盖了。。。

#include <iostream>  #include <queue>  #include <stack>  #include <map>  #include <set>  #include <bitset>  #include <cstdio>  #include <algorithm>  #include <cstring>  #include <climits>  #include <cstdlib>#include <cmath>#include <time.h>#define maxn 5005#define maxm 100005#define eps 1e-10#define mod 1000000009#define INF 0x3f3f3f#define lowbit(x) (x&(-x))  //#define lson o<<1, L, mid  //#define rson o<<1 | 1, mid+1, R  typedef long long LL;//typedef int LL;using namespace std;int H[maxn], NEXT[maxm], V[maxm];int h[maxn], next[maxm], v[maxm];int dfn[maxn], low[maxn], id[maxn];int res[maxn], vis[maxn], ins[maxn];stack<int> s;int top, scc_cnt, n, m;void init(void){top = scc_cnt = 0;memset(h, -1, sizeof h);memset(H, -1, sizeof H);memset(ins, 0, sizeof ins);memset(res, -1, sizeof res);memset(dfn, 0, sizeof dfn);}void read(void){int a, b, cnt = 0;scanf("%d%d", &n, &m);while(m--) {scanf("%d%d", &a, &b);NEXT[cnt] = H[a], H[a] = cnt, V[cnt] = b, cnt++;}}void tarjan(int u){dfn[u] = low[u] = ++top;s.push(u), ins[u] = 1;for(int e = H[u]; ~e; e = NEXT[e])if(!dfn[V[e]]) {tarjan(V[e]);low[u] = min(low[u], low[V[e]]);}else if(ins[V[e]]) low[u] = min(low[u], dfn[V[e]]);if(dfn[u] == low[u]) {int tmp = s.top(); s.pop(), ins[tmp] = 0;++scc_cnt;while(tmp != u) {id[tmp] = scc_cnt;tmp = s.top();s.pop();ins[tmp] = 0;}id[tmp] = scc_cnt;}}void narrow(void){int cnt = 0;for(int i = 1; i <= n; i++)for(int e = H[i]; ~e; e = NEXT[e])next[cnt] = h[id[i]], h[id[i]] = cnt, v[cnt] = id[V[e]], cnt++;}bool dfs(int u){for(int e = h[u]; ~e; e = next[e]) {if(v[e] == u) continue;if(vis[v[e]]) continue;vis[v[e]] = 1;if(res[v[e]] == -1 || dfs(res[v[e]])) {res[v[e]] = u;return true;}}return false;}void work(void){int ans = 0, i;for(i = 1; i <= n; i++)if(!dfn[i]) tarjan(i);narrow();for(i = 1; i <= scc_cnt; i++) {memset(vis, 0, sizeof vis);if(dfs(i)) ans++;}printf("%d\n", scc_cnt-ans);}int main(void){int _;while(scanf("%d", &_)!=EOF) {while(_--) {init();read();work();}}return 0;}


0 0
原创粉丝点击