SSLOJ 1340 最小路徑覆蓋
阿新 • • 發佈:2018-12-19
題目
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 }