1340 最小路径覆盖 最大匹配

版权声明:未知苦处,不信神佛 https://blog.csdn.net/yjy_aii/article/details/85014161

题目

定义: 一个不含圈的有向图G中,G的一个路径覆盖是一个其结点不相交的路径集合P,图中的每一个结点仅包含于P中的某一条路径。路径可以从任意结点开始和结束,且长度也为任意值,包括0。请你求任意一个不含圈的有向图G的最小路径覆盖数。

提示:最小路径覆盖数=G的定点数-最小路径覆盖中的边数
最小路径覆盖数=原图G的顶点数-二分图的最大匹配数

题解

把原图的每个点拆成两个点,然后从有向边的起点向终点连线,其中起点全部放在二分图的同一边。
这时可以把n个点看成独立的一个路径,然后选择一个匹配就是把两个路径连起来。可以看出同一个起点不能连出两条匹配,因为同一条路径方向不能改变,同理同一个终点也是这样,符合匹配的定义。
最后答案=顶点数-最大匹配数

时间复杂度 O ( n 3 ) O(n^3)

代码

#include <cstdio>
#include <cstring>

using namespace std;

int t,n,m,cnt;
int ls[150],ne[20005],y[20005],link[150];
bool cover[150];

bool dfs(int k){
	for (int i=ls[k];i;i=ne[i])
	if (!cover[y[i]]){
		int t=link[y[i]];
		link[y[i]]=k;
		cover[y[i]]=1;
		if (t==0||dfs(t)) return 1;
		link[y[i]]=t;
	}
	return 0;
}

int main(){
	scanf("%d",&t);
	for (;t;t--){
		scanf("%d",&n);
		scanf("%d",&m);
		cnt=0;
		memset(link,0,sizeof(int)*(n+3));
		memset(ls,0,sizeof(int)*(n+3));
		for (int i=1;i<=m;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			ne[++cnt]=ls[a];ls[a]=cnt;y[cnt]=b;
		}
		int ans=n;
		for (int i=1;i<=n;i++){
			memset(cover,0,sizeof(bool)*(n+3));
			if (dfs(i)) ans--;
		}
		printf("%d\n",ans);
	}
}

心之所至,是为天上锦绣;心之所安,是为人间繁华

猜你喜欢

转载自blog.csdn.net/yjy_aii/article/details/85014161