SSLOJ 1340 最小路径覆盖

题目

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 拆成 V x V y 两个点,
   如果有一条有向边 A->B ,那么就加边 A x >B y
   。这样就得到了一个二分图。
   那么 最小路径覆盖=原图的结点数-新图的最大匹配数。
 

代码

 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 }

猜你喜欢

转载自www.cnblogs.com/zjzjzj/p/10146290.html