HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861
最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/article/details/82012572
题意:
把城市至少分成几个块,规则有三
1. A能B,B能到A,那么A,B一定要在一起。
2. 一个城市只能属于一个块。 (说明了是最小不相交覆盖)
3. 在一个块里的城市,任意2点之间必须有路径。
对于规则1,就是说强连通的必须在一起,所以用Tarjan进行缩点,然后,规则2,3就是求DAG(有向无环图)最小路径覆盖。(最小路径覆盖=顶点数-最大匹配)
首先我们需要了解到最小覆盖路径的定义:通俗点将,就是在一个有向图中,找出最少的路径,使得这些路径经过了所有的点。
最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖。
最小不相交路径覆盖:每一条路径经过的顶点各不相同。如图,其最小路径覆盖数为3。即1->3>4,2,5。
最小可相交路径覆盖:每一条路径经过的顶点可以相同。如果其最小路径覆盖数为2。即1->3->4,2->3>5。
特别的,每个点自己也可以称为是路径覆盖,只不过路径的长度是0。
DAG的最小不相交路径覆盖
算法:把原图的每个点V拆成VxVx和VyVy两个点,如果有一条有向边A->B,那么就加边Ax−>ByAx−>By。这样就得到了一个二分图。那么最小路径覆盖=原图的结点数-新图的最大匹配数。
证明:一开始每个点都是独立的为一条路径,总共有n条不相交路径。我们每次在二分图里找一条匹配边就相当于把两条路径合成了一条路径,也就相当于路径数减少了1。所以找到了几条匹配边,路径数就减少了多少。所以有最小路径覆盖=原图的结点数-新图的最大匹配数。
因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。
说的拆点这么高深,其实操作起来超级超级简单,甚至没有操作。
简单的来说,每个顶点都能当成二分图中作为起点的顶点。
至于为什么答案是 n-ans,我谈谈我的理解
用dfs求的ans表示的意思是匹配数,换句话说,就是一条路连着的路径上的点的个数-1
DAG的最小可相交路径覆盖
算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b。然后就转化成了最小不相交路径覆盖问题。
证明:为了连通两个点,某条路径可能经过其它路径的中间点。比如1->3->4,2->4->5。但是如果两个点a和b是连通的,只不过中间需要经过其它的点,那么可以在这两个点之间加边,那么a就可以直达b,不必经过中点的,那么就转化成了最小不相交路径覆盖。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<stack>
using namespace std; int head[5010], used[5010], head1[5010];
int dfn[5010], low[5010], vis[5010], color[5010];
int deep, cnt, cnt1, kinds_color, goal[5010];
stack<int>S; struct Edge
{
int to, next;
}edge[100010], edge1[100010]; void add(int a, int b) //存边
{
edge[++ cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt;
} void Add(int a, int b) //存缩点后的边
{
edge1[++ cnt1].to = b;
edge1[cnt1].next = head1[a];
head1[a] = cnt1;
} void tarjan(int now)
{
dfn[now] = low[now] = ++ deep;
S.push(now);
vis[now] = 1;
for(int i = head[now]; i != 0; i = edge[i].next)
{
int to = edge[i].to;
if(!dfn[to])
{
tarjan(to);
low[now] = min(low[now], low[to]);
}
else if(vis[to])
low[now] = min(low[now], dfn[to]);
}
if(low[now] == dfn[now])
{
kinds_color ++;
while(1)
{
int temp = S.top();
S.pop();
vis[temp] = 0;
color[temp] = kinds_color;
if(temp == now)
break;
}
}
} bool find(int x) //找最大匹配
{
for(int i = head1[x]; i !=0; i = edge1[i].next)
{
int t = edge1[i].to;
if(!used[t])
{
used[t] = 1;
if(!goal[t] || find(goal[t]))
{
goal[t] = x;
return true;
}
}
}
return false;
} int main()
{
int T, n, m;
int a, b, ans;
scanf("%d", &T);
while(T --)
{
deep = cnt = kinds_color = cnt1 = ans = 0;
memset(vis, 0, sizeof(vis));
memset(dfn, 0, sizeof(dfn));
memset(goal, 0, sizeof(goal));
memset(low, 0, sizeof(low));
memset(head, 0, sizeof(head));
memset(head1, 0, sizeof(head1));
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i ++)
{
scanf("%d%d", &a, &b);
add(a, b);
}
for(int i = 1; i <= n; i ++)
{
if(!dfn[i])
tarjan(i);
}
for(int i = 1; i <= n; i ++)
{
for(int j = head[i]; j != 0; j = edge[j].next)
{
int to = edge[j].to;
int x = color[i], y = color[to];
if(x != y)
Add(x, y);
}
}
for(int i = 1; i <= kinds_color; i ++)
{
memset(used, 0 ,sizeof(used));
if(find(i))
ans ++;
}
printf("%d\n", kinds_color - ans);
}
return 0;
}
HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)的更多相关文章
- [luoguP2764] 最小路径覆盖问题(最大流 || 二分图最大匹配)
传送门 可惜洛谷上没有special judge,不然用匈牙利也可以过的,因为匈牙利在增广上有一个顺序问题,所以没有special judge就过不了了. 好在这个题的测试数据比较特殊,如果是网络流的 ...
- HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)
HDU 3861 The King's Problem 题目链接 题意:给定一个有向图,求最少划分成几个部分满足以下条件 互相可达的点必须分到一个集合 一个对点(u, v)必须至少有u可达v或者v可达 ...
- HDU 3861.The King’s Problem 强联通分量+最小路径覆盖
The King’s Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- HDU 3861 The King’s Problem(强连通分量+最小路径覆盖)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意: 在csdn王国里面, 国王有一个新的问题. 这里有N个城市M条单行路,为了让他的王国 ...
- HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)
http://acm.hdu.edu.cn/showproblem.php?pid=3861 题意: 国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意 ...
- HDU 3861 The King’s Problem(tarjan连通图与二分图最小路径覆盖)
题意:给我们一个图,问我们最少能把这个图分成几部分,使得每部分内的任意两点都能至少保证单向连通. 思路:使用tarjan算法求强连通分量然后进行缩点,形成一个新图,易知新图中的每个点内部的内部点都能保 ...
- HDU 3861 The King’s Problem (强连通缩点+DAG最小路径覆盖)
<题目链接> 题目大意: 一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.所有点只能属于一块区域:2,如果两点相互可达,则这两点必然要属于同一区域:3,区域内任意两点 ...
- HDU 3861 The King’s Problem 强连通分量 最小路径覆盖
先找出强连通分量缩点,然后就是最小路径覆盖. 构造一个二分图,把每个点\(i\)拆成两个点\(X_i,Y_i\). 对于原图中的边\(u \to v\),在二分图添加一条边\(X_u \to Y_v\ ...
- hdu 3861 The King’s Problem trajan缩点+二分图匹配
The King’s Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
随机推荐
- RDay1-Problem 1 A
题目描述 给定一个长度为n的正整数序列a[i],计算出有多少个i<j的数对,a[i]+a[j]为二的次幂,也就是说存在一个正整数x满足a[i]+a[j]==2^x. 输入 输入文件A.in. 第 ...
- Jmeter性能测试之进阶Java request的使用
在IDE中引用Jmeter的安装目录lib/ext中两个文件ApacheJMeter_core.jar和ApacheJMeter_java.jar Java request的类需要继承Abstract ...
- Postgresql/Greenplum中将数字转换为字符串TO_CHAR函数前面会多出一个空格
-- 问题1..Postgresql中将数字转换为字符串前面多出一个空格. SELECT TO_CHAR(, '); -- 解决1.使用如下,参数二前面加上fm就可以去掉空格了,如下: SELECT ...
- Codeforces 1109D Sasha and Interesting Fact from Graph Theory (看题解) 组合数学
Sasha and Interesting Fact from Graph Theory n 个 点形成 m 个有标号森林的方案数为 F(n, m) = m * n ^ {n - 1 - m} 然后就 ...
- Facebook授权登录
1.注册开发者账号 登陆facebook开发者平台 (https://developers.facebook.com/), 注册facebook开发者账号. 2.Facebook登录Key Hash配 ...
- Aspnet Mvc 前后端分离项目手记(三)关于restful 风格Url设计
RESTful 不是新东西,简单理解它的核心思想就是最大程度的利用http协议的一些特点,比如uri,比如请求动词,在前后端分离的项目中会有大大的好处 ,好的设计的url简单明了,胜过详细的说明文档. ...
- Win10 清理自带APP
如果想一次性把它们全都删掉,请输入: Get-AppxPackage -AllUsers | Remove-AppxPackage 但是如果你先建一个账户,以上应用就会再次全部出现,不想这样的话可以输 ...
- line-height:1.5和line-height:150%的区别
1. 给你个数,孩子自己算吧 line-height:1.5 父元素设置line-height:1.5会直接继承给子元素,子元素根据自己的font-size再去计算子元素自己的line-height ...
- DWM1000 三基站一标签定位HEX
蓝点DWM1000 模块已经打样测试完毕,有兴趣的可以申请购买了,更多信息参见 蓝点论坛 HEX 下载链接参见论坛:http://bphero.com.cn/forum.php?mod=viewthr ...
- js两个箭头 =>()=>()
request(_ action)let withStatus =status =>action=> R.merge(action, (status])let request = with ...