题目描述
一个不含圈的有向图G中,G的一个路径覆盖是一个其结点不相交的路径集合P,图中的每一个结点仅包含于P中的某一条路径。路径可以从任意结点开始和结束,且长度也为任意值,包括0。请你求任意一个不含圈的有向图G的最小路径覆盖数。
输入输出格式
输入格式
t 表示有t组数据;n 表示n个顶点(n<=120);m 表示有m条边; 接下来m行,每行有两个数 i,j表示一条有向边。
输出格式
最小路径覆盖数
输入输出样例
输入样例#1:
2
4
3
3 4
1 3
2 3
3
3
1 3
1 2
2 3
输出样例#1:
2
1
题目解析
把原图的每个点V拆成Vx和Vy两个点,如果有一条有向边A->B,那么就加边Ax−>By。这样就得到了一个二分图。
那么最小路径覆盖=原图的结点数-新图的最大匹配数。
代码
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int t,n,m,u,v,link[125],ans;
vector<int> a[125];
bool flag[125];
bool find(int x)
{
for(int i=0;i<a[x].size();i++)
if(!flag[a[x][i]])
{
int j=a[x][i];
flag[j]=1;
int q=link[j];
link[j]=x;
if(!q||find(q)) return true;
link[j]=q;
}
return false;
}//最大匹配
int main()
{
cin>>t;
while(t>0)
{
t--;
cin>>n>>m;
for(int i=1;i<=n;i++)
a[i].clear();
memset(link,0,sizeof(link));
ans=0;//初始化
for(int i=1;i<=m;i++)
{
cin>>u>>v;
a[u].push_back(v);
}
for(int i=1;i<=n;i++)
{
memset(flag,0,sizeof(flag));
ans+=find(i);
}
cout<<n-ans<<endl;//最小路径覆盖=原图的结点数-新图的最大匹配数
}
}