poj2594 机器人寻找宝藏(最小路径覆盖)
题目来源:http://poj.org/problem?id=2594
参考博客:http://www.cnblogs.com/ka200812/archive/2011/07/31/2122641.html
题解:
最小路径覆盖=|P|-最大匹配数
单向图且没有循环,不可能存在a到b,b又到a,并且可以经过已经经过的点,所以对整个图进行处理,间接连接的点可以看作是直接连接
将整个图分成两边,点与点二分匹配,与平时的两种不同物体匹配不同
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <algorithm> using namespace std; const int maxn=500+5; int ma[maxn][maxn],match[maxn]; bool used[maxn]; int n; void floyed(){ for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(ma[i][k]+ma[k][j]==2)ma[i][j]=1; } bool dfs(int x){ for(int i=1;i<=n;i++){ if(ma[x][i]&&used[i]==0){ used[i]=1; if(match[i]==0||dfs(match[i])){ match[i]=x; return 1; } } } return 0; } int solve(){ memset(match,0,sizeof(match)); int ans=0; for(int i=1;i<=n;i++){ memset(used,0,sizeof(used)); if(dfs(i))ans++; } return n-ans; } int main() { int m; while(scanf("%d %d",&n,&m)==2){ if(n==0&&m==0)break; memset(ma,0,sizeof(ma)); for(int i=1;i<=m;i++){ int a,b; scanf("%d %d",&a,&b); ma[a][b]=1; } floyed(); cout<<solve()<<endl; } return 0; }