Floyd传递闭包+DAG的最小路径覆盖
先来一次Floyd传递闭包,然后再求最大匹配,n-最大匹配就是答案
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<vector> using namespace std; const int MAXN=550; int linker[MAXN]; bool used[MAXN]; vector<int>Map[MAXN]; int uN; int jz[MAXN][MAXN]; int n,m; bool dfs(int u) { for(int i=0; i<Map[u].size(); i++) { if(!used[Map[u][i]]) { used[Map[u][i]]=true; if(linker[Map[u][i]]==-1||dfs(linker[Map[u][i]])) { linker[Map[u][i]]=u; return true; } } } return false; } int hungary() { int u; int res=0; memset(linker,-1,sizeof(linker)); for(u=1; u<=uN; u++) { memset(used,false,sizeof(used)); if(dfs(u)) res++; } return res; } void floyd() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(jz[i][k]&&jz[k][j]) jz[i][j]=1; } int main() { int u,k,v; while(scanf("%d%d",&n,&m)!=EOF) { memset(jz,0,sizeof jz); if(n==0&&m==0) break; for(int i=0; i<=n; i++) Map[i].clear(); for(int i=0; i<m; i++) { scanf("%d%d",&u,&v); jz[u][v]=1; } floyd(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(jz[i][j]) Map[i].push_back(j); uN=n; printf("%d ",n-hungary()); } return 0; }