算法设计与分析 6.2 路径覆盖

★题目描述

有向无环图上一条简单路径 V0->V1->. . .->Vl (V0可能等于Vl)覆盖了这条路径上的所有节点。

请找出一个简单路径的集合,使得每个节点恰好被覆盖一次,输出路径的最少条数。

★输入格式

输入的第一行两个数字n,m(1<=n<=100,1<=m<=n*(n-1)/2)$,表示有向无环图的节点数与边数。

接下来m行每行两个数字a,b(1<=a,b<=m)代表一条由a指向b的有向边。

★输出格式

输出一个整数表示最少需要的路径条数。

★样例输入

11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11

★样例输出

3

★提示

三条路径分别为(1->4->7->10->11),(2->5->8),(3->6->9)。

★参考代码

/*
也是一道二分图最大匹配的题

题目所问的最少的路径数 = 节点数n - 最大匹配数 
*/
#include<bits/stdc++.h>
using namespace std;

int Match[101];
int Visit[101];

int H[101];
struct Edge{
	int end,nxt; //尾端点,头节点相同的下一条边 
}E[5000];

int idx=0;
void AddEdge(int u, int v){
	++idx;
	E[idx].end=v, E[idx].nxt=H[u];
	H[u]=idx;
}

int find(int x){
	for(int i=H[x]; i!=0; i=E[i].nxt){
		int e=E[i].end;
		if(Visit[e]==0){
			Visit[e]=1;
			if(Match[e]==0 || find(Match[e])){
				Match[e]=x;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	int n,m;
	cin>>n>>m;
	
	int u,v;
	while(m--){
		cin>>u>>v;
		AddEdge(u,v);
	} 
	
	int res=0;
	memset(Match, 0, sizeof(Match));
	for(int i=1; i<=n; ++i){
		memset(Visit, 0, sizeof(Visit));
		res += find(i);
	}
	
	cout<<n-res<<endl;
	return 0;
} 
原文地址:https://www.cnblogs.com/yejifeng/p/12097510.html