这题与裸的二分图最小路径覆盖的区别是结点可重复走,从而变为了传递闭包的最小路径覆盖。
具体做法是用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 }