题目链接: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. Android dialog使用

    翻译自:开发->API 指南->User Interface & Navigation->Dialogs 注意: dialog是一个基类,但是我们应该尽可能避免直接使用dia ...

  2. Oracle的基本数据类型(常用)

    转自:https://www.2cto.com/database/201810/783959.html 1.字符型 Char 固定长度字符串 占2000个字节 Varchar2 可变长度字符串 占40 ...

  3. ADOQuery.Parameters: Property Parameters does not exist

    Exception class EReadError with message 'Property Parameters does not exist'. Exception class EReadE ...

  4. TFrame bug

    delphi 10.1.2 工程里有很多fram 正确的工程文件dproj中fram的定义是 <DCCReference Include="Unit15frame.pas"& ...

  5. iOS 申请distribution证书, 公钥,私钥

    私钥只有在本机生成CSR文件的时候会产生,公钥会在CSR文件传给apple时,apple产生.

  6. ubuntu 安装oracle客户端

    from: http://webikon.com/cases/installing-oracle-sql-plus-client-on-ubuntu Installing Oracle SQL*Plu ...

  7. Zookeeper 在Linux系统的安装

    注册中心Zookeeper 官方推荐使用 zookeeper 注册中心.注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小. Z ...

  8. CocosCreator 自定义TypeScript在VsCode的提示数据

    在assets文件夹外新建xx.d.ts文件如:global.d.ts global.d.ts declare class UserData{ node:cc.Node; name:string; } ...

  9. linux 3.10中完成量的使用

    完成量是基于等待队列设计的,所以显然不能在中断上下文使用完成量. struct completion { unsigned int done; wait_queue_head_t wait; }; 我 ...

  10. KVM虚拟化技术(三)KVM环境预配

    一.平台操作系统安装 选择合适的操作系统,此处选用CentOS 7 系统可最小化安装,也可标准安装: 如果要远程连接,建议安装VNC-Server 将防火墙配置可通信,SELINUX设为permiss ...