2021.7.12提高B组模拟1T4 Vani和Cl2捉迷藏(最大匹配)
Posted SSL_LKJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.7.12提高B组模拟1T4 Vani和Cl2捉迷藏(最大匹配)相关的知识,希望对你有一定的参考价值。
Vani和Cl2捉迷藏
题目大意
在一个DAG(有向无环图)中找出多个互不相通的点
输入样例
4 4
1 2
3 2
3 4
4 2
输出样例
2
解题思路
这题实质是求DAG的最长反链长度
最小链覆盖我们则可以用 最大匹配(匈牙利算法) 来做
但是这样搞下来,我们只能拿95分
所以我们要引入一个东西传递闭包
可以使一些本来会相交的路径分离开
如图
经过传递闭包后,就能使1和4 ,2和5直接相连,不再相交,这样就完成了转换
建议用Floyd
AC代码
#include<cstring>
#include<cstdio>
using namespace std;
long long n,m,T,x,y,tot,answer,head[1005],cover[1005],father[1005],f[1005][1005];
struct node//结构体
{
long long to,next;
}a[1000005];
void add(long long x,long long y)//邻接表
{
a[++tot]=(node){y,head[x]};
head[x]=tot;
}
bool dfs(long long x)//dfs
{
if(x==0)return true;
for(long long i=head[x];i;i=a[i].next)
if(cover[a[i].to]==0)
{
cover[a[i].to]=1;
long long sum=father[a[i].to];
father[a[i].to]=x;
if(sum==0||dfs(sum))return true;
father[a[i].to]=sum;
}
return false;
}
int main()
{
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
f[x][y]=1;
}
for(long long k=1;k<=n;k++)//传递闭包
for(long long i=1;i<=n;i++)
for(long long j=1;j<=n;j++)
if(f[i][k]+f[k][j]==2)
f[i][j]=1;
for(long long i=1;i<=n;i++)//建边
for(long long j=1;j<=n;j++)
if(f[i][j]==1)add(i,j);
for(long long i=1;i<=n;i++)//匈牙利算法
{
memset(cover,0,sizeof(cover));
dfs(i);
}
for(long long i=1;i<=n;i++)
if(father[i]!=0)answer++;
printf("%lld\\n",n-answer);
return 0;
}
谢谢
以上是关于2021.7.12提高B组模拟1T4 Vani和Cl2捉迷藏(最大匹配)的主要内容,如果未能解决你的问题,请参考以下文章