HDU 3861 The King’s Problem(tarjan连通图与二分图最小路径覆盖)
题意:给我们一个图,问我们最少能把这个图分成几部分,使得每部分内的任意两点都能至少保证单向连通。
思路:使用tarjan算法求强连通分量然后进行缩点,形成一个新图,易知新图中的每个点内部的内部点都能保证双向连通,而新图中的点都是单向无环的,这个时候题目中要求的划分部分的条件,其实就是求最短路径覆盖(需要好好想一想),最短路径覆盖 = 结点个数 - 最大匹配值。
这个题我当时把j写成了i,就这么一个小地方,找了快20分钟,还死活发现不了。。真是晕死了~
最后我想总结一下这个题:
这个题很巧妙的把割点和二分图巧妙的结合了在一起,最后变成了最小路径覆盖问题,我就把我对最短路径覆盖的理解说一下吧:
最短路径覆盖,针对有向图而言,是找到最少的路径使覆盖所有的点,每个点的入度与出度最多是1,他的计算方法是 最短路径覆盖 = 结点个数 - 最大匹配值。
证明: 如果有n个点,0个匹配,那我们就有n条路径(一个单独的点也要被看作一条路径),当我们找到一个u和v的匹配的时候,我们需要的路径就少一,以此类推,就证明出了以上结论。
我在观察匹配算法的深搜树的时候发现了,我并没有去按照分两边集合的方式去考虑,而是按照父亲优先让出的原则去思考的,这个想法基于每个点只能最多有一个入度和出度,而且在深搜的过程中,每次直接匹配或迭代匹配都会使结果加1,但是迭代匹配有可能进行进行多次,但结果只加了1,其实是后来在的遍历中计算了结果,这也是为什么vis数组必须清空的原因之一。在匹配过程中我们并不关心匹配的方案,只关心匹配的最大数值,同一个值有可能对应多条匹配方案是当然的,但在二分图的题目中,很少有要求输出方案的,有的话也是随便输出一条,那直接输出我们随机匹配的match就好了~(仅代表个人看法)。
#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
#define maxn 5050
struct EDGE
{
int to,nxt;
} edge[maxn*];
EDGE newmap[maxn*];
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,,sizeof(dfn));
memset(low,,sizeof(low));
memset(id,,sizeof(id));
memset(head,-,sizeof(head));
memset(newhead,-,sizeof(newhead));
tot = ,sum = ;
tot1 = ;
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 != -; 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 != -;i = newmap[i].nxt)
{
int v = newmap[i].to;
if(!vis[v])
{
vis[v] = ;
if(match[v] == - || Find(match[v]))
{
match[v] = u;
return true;
}
}
}
return false;
}
int erfen()
{
int ans = ;
memset(match,-,sizeof(match));
for(int i = ;i <= sum;i++)
{
for(int j = ;j <= sum;j++) vis[j] = ;
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 = ; i < m; i++)
{
scanf("%d%d",&x,&y);
edge[i].to = y;
edge[i].nxt = head[x];
head[x] = i;
}
for(int i = ;i <= n;i++)
{
if(!dfn[i])
tarjan(i);
}
for(int i = ;i <= n;i++)
{
int u = i;
for(int j = head[u];j != -;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 ;
}
HDU 3861 The King’s Problem(tarjan连通图与二分图最小路径覆盖)的更多相关文章
- HDU 3861 The King’s Problem (强连通缩点+DAG最小路径覆盖)
<题目链接> 题目大意: 一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.所有点只能属于一块区域:2,如果两点相互可达,则这两点必然要属于同一区域:3,区域内任意两点 ...
- 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 ...
- hdu3861 The King’s Problem 强连通缩点+DAG最小路径覆盖
对多校赛的题目,我深感无力.题目看不懂,英语是能懂的,题目具体的要求以及需要怎么做没有头绪.样例怎么来的都不明白.好吧,看题解吧. http://www.cnblogs.com/kane0526/ar ...
- 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 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/ar ...
- HDU 3861 The King’s Problem(强连通分量+最小路径覆盖)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意: 在csdn王国里面, 国王有一个新的问题. 这里有N个城市M条单行路,为了让他的王国 ...
- 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 题意: 国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意 ...
随机推荐
- ev=ev || window.event 与 ev = window.event || ev 区别
event是事件对象(也是window的属性),但不是标准的,只有IE支持.在W3C标准支持的浏览器下事件对象是引发事件函数的第一个参数,参数名随意.var oEvent = ev || event; ...
- eclipse和tomcat整合之后每次发布server.xml被修改(转)
eclipse每次发布,server.xml和context.xml总是被还原 直接找到eclispse工程下的server工程,把里面的相应的server.xml和context.xml修改了即可, ...
- HeapSpray初窥(2014.12)
注:环境是xp+ie8 1.HeapSpray简介 Windows的堆因为动态分配和释放的特点,其看起来是不连续(没有规律的),但是仍可以找到一定的规律:大量的连续分配会更倾向使用连续的地址,减少了碎 ...
- 利用Ajax实现前端与.net后端实现数据交互
使用场景和需求:用户在地址栏输入请求地址,先.net服务器发送页面请求,该页面包含Echart图表,在页面中向.net后端发送数据请求,获取数据后,将数据填充到Echart图表中.其中包含带参与不带参 ...
- 观看网上的N多教程有感
MD只想说一句,我擦. 长篇大论,有个叼毛用呀,显示你文采.... 糟粕真TMD多,直接简单的步骤多好,不要显示的你有多专业,其实就是一个二逼. 还有N多论坛,扯淡的人更多.
- HTTP 返回状态值详解
当用户点击或搜索引擎向网站服务器发出浏览请求时,服务器将返回Http Header Http头信息状态码,常见几种如下: 1.Http/1.1 200 OK 访问正常 表示成功访问,为网站可正常访问 ...
- TD8.0迁移到QC9.2,自动迁移失败,手动迁移
源机器A:TD8.0+SQLServer2000目标机器B:QC9.2+SQLServer2000 一:自动迁移,1.在A在A上安装QC迁移工具,然后在B中点击TOOLS>>Migrati ...
- 如何禁用电脑USB接口
方法一,BIOS设置法 重新启动计算机,在开机过程中,点击键盘上的“Delete”键,进入BIOS设置界面,选择“Integrated Peripherals”选项,展开后将“USB 1.1 Cont ...
- kloxo面板教程-折腾了一天
------------------------------------------------------------------------------- 前一晚安装了掉线,不得不重新来,有点慢, ...
- Android面试题集锦 (转)
转自:http://xiechengfa.iteye.com/blog/1044721 一些常见的Android面试基础题做下总结,看看你能做出多少道? 1. Intent的几种有关Activity启 ...