题意:给我们一个图,问我们最少能把这个图分成几部分,使得每部分内的任意两点都能至少保证单向连通。

  思路:使用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连通图与二分图最小路径覆盖)的更多相关文章

  1. HDU 3861 The King’s Problem (强连通缩点+DAG最小路径覆盖)

    <题目链接> 题目大意: 一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.所有点只能属于一块区域:2,如果两点相互可达,则这两点必然要属于同一区域:3,区域内任意两点 ...

  2. 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 ...

  3. hdu3861 The King’s Problem 强连通缩点+DAG最小路径覆盖

    对多校赛的题目,我深感无力.题目看不懂,英语是能懂的,题目具体的要求以及需要怎么做没有头绪.样例怎么来的都不明白.好吧,看题解吧. http://www.cnblogs.com/kane0526/ar ...

  4. HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)

    HDU 3861 The King's Problem 题目链接 题意:给定一个有向图,求最少划分成几个部分满足以下条件 互相可达的点必须分到一个集合 一个对点(u, v)必须至少有u可达v或者v可达 ...

  5. HDU 3861.The King’s Problem 强联通分量+最小路径覆盖

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  6. HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/ar ...

  7. HDU 3861 The King’s Problem(强连通分量+最小路径覆盖)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意: 在csdn王国里面, 国王有一个新的问题. 这里有N个城市M条单行路,为了让他的王国 ...

  8. hdu——3861 The King’s Problem

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  9. HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=3861 题意: 国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意 ...

随机推荐

  1. MyBatisNet 学习

    SQL Maps Sql Maps是这个框架中最激动人心的部分,它是整个iBATIS Database Layer的核心价值所在.通过使用Sql Maps你可以显著的节约数据库操作的代码量.SQL M ...

  2. C++中构造函数或析构函数定义为private

    转自:http://www.blogjava.net/fhtdy2004/archive/2009/05/30/278971.html 很多情况下要求当前的程序中只有一个object.例如一个程序只有 ...

  3. Spring的Resource

    通过Spring Resource接口获取资源(取自http://haohaoxuexi.iteye.com/blog/2016305)目录1 Resource简介2 通过ResourceLoader ...

  4. 第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如:  List list = new ArrayList();  list.add(“Hello”);  list.add(“World”);  list.add(“Learn”); //此时list 为Hello World Learn  r

    package zuoye; import java.util.ArrayList; import java.util.List; public class Reverse01 { public st ...

  5. html5 --基础笔记2

    1.autocomplete 可以给表单本身(不是fieldset)设置属性来禁用整个表单的自动完成功能 <form id="" method="" au ...

  6. jquery各版本区别

     jquery版本区别:          1.3一般功能够 1.4.2一般功能够而且稳定 1.7+比较新特性 2不支持老IE 兼容的话最好选 1.x.稳定性就用1.7或者1.4,其中1.4的体积相对 ...

  7. oracle Database Link

    1 Database Link 的创建: 有两个数据库服务器A/B, 其中A的IP地址为172.20.36.245, 服务器B为本机.服务器B上的数据库实例名为ORCL,在本机上的服务监听配置上有服务 ...

  8. android常用工具类

    import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkIn ...

  9. js第一天 innerHTML和value 的区别

    innerHTML在JS是双向功能:获取对象的内容 或 向对象插入内容:如:<div id="aa">这是内容</div> ,我们可以通过 document ...

  10. hdu_3068_最长回文(Manacher)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:给你一个字符串,让你求最长的回文子串. 题解:数据量比较大,暴力O(n2)会超时,直接上马 ...