题目
Description
定义: 一个不含圈的有向图G中,G的一个路径覆盖是一个其结点不相交的路径集合P,图中的每一个结点仅包含于P中的某一条路径。路径可以从任意结点开始和结束,且长度也为任意值,包括0。请你求任意一个不含圈的有向图G的最小路径覆盖数。
提示:最小路径覆盖数=G的定点数-最小路径覆盖中的边数
最小路径覆盖数=原图G的顶点数-二分图的最大匹配数
Input
t 表示有t组数据;n 表示n个顶点(n<=120);m 表示有m条边;
接下来m行,每行有两个数 i,j表示一条有向边。
Output
最小路径覆盖数
Sample Input
2
4
3
3 4
1 3
2 3
3
3
1 3
1 2
2 3
Sample Output
2
1
分析
把原图的每个点V拆成Vx和Vy两个点,
如果有一条有向边A->B,那么就加边Ax−>By
。这样就得到了一个二分图。
那么最小路径覆盖=原图的结点数-新图的最大匹配数。
代码
1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 int n,m,x,y; 5 bool cover[10001]; 6 int link[10001]; 7 vector <int> f[10001]; 8 bool find(int x) //匹配 9 { 10 for (int i=0;i<f[x].size();i++) 11 { 12 if (!cover[f[x][i]]) 13 { 14 cover[f[x][i]]=true; 15 int q=link[f[x][i]]; 16 link[f[x][i]]=x; 17 if (q==0||find(q)) return true; 18 link[f[x][i]]=q; 19 } 20 } 21 return false; 22 } 23 int main () 24 { 25 int T; 26 cin>>T; 27 for (int k=1;k<=T;k++) 28 { 29 cin>>n>>m; 30 memset(link,0,sizeof(link)); 31 for (int i=0;i<10000;i++) //清空向量 32 f[i].clear(); 33 for (int i=1;i<=m;i++) 34 { 35 cin>>x>>y; 36 f[x].push_back(y); 37 } 38 int ans=0; 39 for (int i=1;i<=n;i++) 40 { 41 memset(cover,false,sizeof(cover)); 42 ans+=find(i); 43 } 44 cout<<n-ans<<endl; 45 } 46 }