這題與裸的二分圖最小路徑覆蓋的區別是結點可重複走,從而變爲了傳遞閉包的最小路徑覆蓋。ios
具體作法是用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 }