poj2594最小路径覆盖的一点点变形

这题与裸的二分图最小路径覆盖的区别是结点可重复走,从而变为了传递闭包的最小路径覆盖。

具体做法是用floyd将凡是能连通的结点都标记为能直接走到,然后建一条边,最后用最小路径覆盖做就行了~

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <string>
 8 #include <vector>
 9 #include <queue>
10 #include <cmath>
11 #include <stack>
12 //#include <map>
13 #include <cmath>
14 #include <set>
15 #include <climits>
16 #define INF 0x7fffffff
17 #define finc(i,a,b) for(i=a;i<=b;i++)
18 #define fdec(i,a,b) for(i=a;i>=b;i--)
19 #define MAXN 301
20 #define MAXM 100002
21 using namespace std;
22 int n,m;
23 int linker[1000];
24 int g[1050][1050];
25 int vis[1050];
26 int used[1050];
27 bool dfs(int u)
28 {
29     int v;
30     finc(v,1,n){
31         if(g[u][v]&&!vis[v])
32         {
33             vis[v]=1;
34             if(linker[v]==-1||dfs(linker[v]))
35             {
36                 linker[v]=u;
37                 return true;
38             }
39         }
40     }
41     return false;
42 }
43 
44 int hungary()
45 {
46     int u,res=0;
47     memset(linker,-1,sizeof(linker));
48     finc(u,1,n){
49         memcpy(vis,used,sizeof(used));
50         if(dfs(u))  res++;
51     }
52     return res;
53 }
54 int floyd()
55 {
56     int i,j,k;
57     finc(k,1,n)
58         finc(i,1,n)
59             finc(j,1,n)
60                 if(i!=j&&g[i][k]&&g[k][j])
61                     g[i][j]=1;
62 
63 }
64 int main()
65 {
66     int i,j,x,y,id,k;
67     while(~scanf("%d%d",&n,&m)&&(n||m))
68     {
69         memset(g,0,sizeof(g));
70         finc(i,1,m){
71             scanf("%d%d",&x,&y);
72             g[x][y]=1;
73         }
74         floyd();
75         cout<<n-hungary()<<endl;
76     }
77 
78 }
View Code
原文地址:https://www.cnblogs.com/-dante-/p/3267095.html