题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861

题意:输入t,表示t个样例。接下来每个样例第一行有两个数n,m表示点数和有向边的数量,接下来输入m条有向边,现在要我们把点划分成最少的块,每个块里面的点两两之间要至少有一条有向边可以从其中一个点到另一个点。

思路:分成的区域里面两个点之间至少要有一个点可以到达另一个点,并且要区域数最少,那么就是求最小路径覆盖,但是要求最小路径覆盖的前提是要是无环,所以我们要先用tarjan算法缩点,然后在在缩完点的图上面建一个二分图来求最小路径覆盖。

最小路径覆盖我是刚刚接触,推荐博客:https://www.cnblogs.com/jianglangcaijin/p/5989907.html

这里我用的是链式前向星,没有用vector,代码长了一点

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 5005
struct node{
int v,next;
}edge1[maxn**],edge2[maxn**];
int head1[maxn],dfn[maxn],low[maxn],s[maxn],color[maxn];
int head2[maxn],pre[maxn*];
bool vis[maxn*];
int top,cnt1,time,color_num;
int cnt2,ans;
int n,m,k,t;
void init()
{
memset(head1,-,sizeof(head1));
memset(dfn,,sizeof(dfn));
memset(vis,false,sizeof(vis));
memset(pre,-,sizeof(pre));
memset(head2,-,sizeof(head2));
cnt1=time=color_num=top=;
cnt2=ans=;
}
void addedge1(int u,int v)//第一次建图添加边
{
edge1[++cnt1].v=v;
edge1[cnt1].next=head1[u];
head1[u]=cnt1;
}
void addedge2(int u,int v)//第二次建图添加边
{
edge2[++cnt2].v=v;
edge2[cnt2].next=head2[u];
head2[u]=cnt2; }
void DFS(int u)//缩点(染色)
{
low[u]=dfn[u]=++time;
vis[u]=true;
s[top++]=u;
for(int i=head1[u];i!=-;i=edge1[i].next)
{
int v=edge1[i].v;
if(!dfn[v])
{
DFS(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
color_num++;
int v;
do{
v=s[--top];
vis[v]=false;
color[v]=color_num;
}while(u!=v);
}
}
void tarjan()
{
for(int i=;i<=n;i++)
{
if(!dfn[i])
DFS(i);
}
}
void rebuild()
{
for(int i=;i<=n;i++)
{
for(int j=head1[i];j!=-;j=edge1[j].next)
{
int v=edge1[j].v;
int a=color[i];
int b=color[v];
if(a!=b)
addedge2(a,b);//建一个二分图
//最小路径覆盖就是点数减最大匹配,注意前提是图里面无环,所以要先缩点
}
}
}
bool hungry_DFS(int u)//求最大匹配
{
for(int i=head2[u];i!=-;i=edge2[i].next)
{
int v=edge2[i].v;
if(vis[v])
continue;
vis[v]=true;
if(pre[v]==-||hungry_DFS(pre[v]))
{
pre[v]=u;
return true;
}
}
return false;
}
void hungry()
{
for(int i=;i<=color_num;i++)
{
memset(vis,false,sizeof(vis));
if(hungry_DFS(i))
ans++;
}
printf("%d\n",color_num-ans);//注意这里是缩点之后的点数减最大匹配数
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
int u,v;
for(int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
addedge1(u,v);//第一次建图
}
tarjan();//缩点
rebuild();//第二次建图
hungry();//求最大匹配
}
return ;
}

缩点+最小路径覆盖 hdu 3861的更多相关文章

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

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

  2. 【HDOJ3861】【Tarjan缩点+最小路径覆盖】

    http://acm.hdu.edu.cn/showproblem.php?pid=3861 The King’s Problem Time Limit: 2000/1000 MS (Java/Oth ...

  3. Light OJ 1429 Assassin`s Creed (II) BFS+缩点+最小路径覆盖

    题目来源:Light OJ 1429 Assassin`s Creed (II) 题意:最少几个人走全然图 能够反复走 有向图 思路:假设是DAG图而且每一个点不能反复走 那么就是裸的最小路径覆盖 如 ...

  4. Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

    题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 ...

  5. Graph_Master(连通分量_C_Trajan缩点+最小路径覆盖)

    hdu_3861 题目大意:给定一张有向图,若<u,v>可达(u可以走到v,或者 v可以走到u),则<u,v>需被划分在统一城邦,问最小划分城邦数. 题解:比较裸的题,可以看出 ...

  6. 最小路径覆盖 hdu 1151 hdu 3335

    Air Raid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  7. HDU 3861 The King’s Problem(tarjan缩点+最小路径覆盖:sig-最大二分匹配数,经典题)

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

  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 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/ar ...

随机推荐

  1. 2018年1月21日--2月4日 NAS

    二十号去比赛时,与同事闲聊时说起家庭服务器,后来搜到nas(网络附着存储器),找到freenas,突然觉得很有用,手机拍了大量的照片视频,存储在电脑,已经换过几次硬盘了,对于这些珍贵的资料,万一硬盘坏 ...

  2. day07-多表查询

    本节重点: 多表连接查询 符合条件连接查询 子查询 准备工作:准备两张表,部门表(department).员工表(employee) create table department( id int, ...

  3. Django--views(视图层)

    路径匹配后-----传给视图函数 一.视图函数 视图层,熟练掌握两个对象即可:请求对象(request)和响应对象(HttpResponse) 一个视图函数,简称视图,是一个简单的Python 函数, ...

  4. EventBus 源码学习

    打开一看,原来相关代码并不多,下面看下细节 主要方法也就是注册,取消注册和发送事件,可以看到两个主要的变量就是subscribers和dispatcher public void register(O ...

  5. jenkins系列_使用scp命令进行远程文件复制遇到的坑

    转自:https://blog.csdn.net/kingboyworld/article/details/78905553 一.场景介绍 项目为微服务项目,使用jenkins进行统一部署.基本思路是 ...

  6. HashMap 实现总结

    Entry类中需包含键值的hash值,防止resize时的重复计算: Map容量为2的整幂,可使用位操作取代取余操作提高效率: resize时需要将原table的桶内数据置null,利于垃圾回收: h ...

  7. 9.mysql-存储过程.md

    目录 创建 创建 -- 创建存储过程 DELIMITER $ -- 声明存储过程的结束符 CREATE PROCEDURE pro_test() --存储过程名称(参数列表) BEGIN -- 开始 ...

  8. Hibernate 再接触 关系映射 一对一单向外键联合主键关联

    例子: Husband.java package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persiste ...

  9. Java学习06 (第一遍) - JSP与Servlet

    EL(Expression Language) <% User user=(User)session.getAttribute("user"); Dept dept=user ...

  10. Kubernetes K8s

    1 Kubernetes入门及概念介绍 Kubernetes(K8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展.开源将Docker 看成Kubernetes内部使用的低级别组 ...