hdu3861The King’s Problem(缩点+二分图匹配(匈牙利))

hdu3861The King’s Problem(缩点+二分图匹配(匈牙利)),第1张

概述传送门题目描述:IntheKingdomofSilence,thekinghasanewproblem.ThereareNcitiesinthekingdomandthereareMdirectionalroadsbetweenthecities.Thatmeansthatifthereisaroadfromutov,youcanonlygofromcityutocityv,butcan’tg

传送门

题目描述:

In the Kingdom of Silence, the king has a new problem. There are N citIEs in the kingdom and there are M directional roads between the citIEs. That means that if there is a road from u to v, you can only go from city u to city v, but can’t go from city v to city u. In order to rule his kingdom more effectively, the king want to divIDe his kingdom into several states, and each city must belong to exactly one state. What’s more, for each pair of city (u, v), if there is one way to go from u to v and go from v to u, (u, v) have to belong to a same state. And the king must insure that in each state we can ether go from u to v or go from v to u between every pair of citIEs (u, v) without passing any city which belongs to other state.
  Now the king asks for your help, he wants to kNow the least number of states he have to divIDe the kingdom into.

题目大意:给咱们一个有向图,让我们划分,原图中在环内(强连通)的点必须分配到一起,可以按路径划分,一个点只出现在一条路径上,求把划分的数目最小

思路:环内的点必须在一个划分块中的话,那就先缩点,弄成无环图再说,然后就是最小路径覆盖裸题了,用的是匈牙利的二分图匹配,虽然没做过,但是抄了书上的模板居然oneA了,有点开心^_^

AC代码:

#include<bits/stdc++.h>using namespace std;const int maxn = 100100;typedef long long ll;struct edge {    int f, t, nxt;}e[maxn << 1];int hd[maxn], tot;voID add(int f, int t) {    e[++tot] = { f,t,hd[f] };    hd[f] = tot;}int n, m;int low[maxn], dfn[maxn], cnt;int stk[maxn], sk, instk[maxn];int col[maxn], colnum;int match[maxn], vis[maxn];voID init() {    memset(match, 0, sizeof(match));    memset(dfn, 0, sizeof(dfn));    memset(col, 0, sizeof(col));    memset(hd, 0, sizeof(hd));    tot = cnt = colnum = 0;}voID tarjan(int u) {//缩点模板    low[u] = dfn[u] = ++cnt;    stk[++sk] = u;    instk[u] = 1;    for (int i = hd[u]; i; i = e[i].nxt) {        int v = e[i].t;        if (!dfn[v]) {            tarjan(v);            low[u] = min(low[u], low[v]);        }        else if (instk[v]) {            low[u] = min(low[u], dfn[v]);        }    }    if (low[u] == dfn[u]) {        colnum++;        while (1) {            int v = stk[sk--];            instk[v] = 0;            col[v] = colnum;            if (v == u)break;        }    }}bool dfs(int u) {//匈牙利模板    for (int i = hd[u]; i; i= e[i].nxt) {        int v = e[i].t;        if (vis[v])continue;//已经尝试过用V来匹配了,没有成功,就不要他了        vis[v] = 1;        if (!match[v] || dfs(match[v])) {            //如果v还没有匹配的人选,或者让之前与v匹配的节点找其他点去匹配,如果成功了就让v与自己匹配            match[v] = u;            return true;        }    }    return false;}int main() {    //freopen("test.txt", "r", stdin);    int t; scanf("%d", &t);    while (t--) {        scanf("%d%d", &n, &m);        init();        for (int i = 1; i <= m;i++) {            int a, b; scanf("%d%d", &a, &b);            add(a, b);        }        for (int i = 1; i <= n; i++) {            if (!dfn[i]) {                tarjan(i);            }        }        memset(hd, 0, sizeof(hd)); tot = 0;//将就之前的数组用,之前的图没必要存在了        for (int i = 1; i <= m; i++) {//遍历所有边            int u = e[i].f, v = e[i].t;            if (col[u] != col[v]) {//把起始点不在同一连通分量的点重新连边                add(col[u], col[v]);            }        }        int sum = 0;        for (int i = 1; i <= colnum; i++) {//二分图匹配            memset(vis, 0, sizeof(vis));            if (dfs(i))sum++;        }        printf("%d\n",colnum-sum);//原节点个数-匹配最大数目就是最小路径覆盖    }    return 0;}

 

总结

以上是内存溢出为你收集整理的hdu3861The King’s Problem(缩点+二分图匹配(匈牙利))全部内容,希望文章能够帮你解决hdu3861The King’s Problem(缩点+二分图匹配(匈牙利))所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1241586.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存