二分图——最大不可互相到达数 = 最小路径覆盖数
study from:
https://blog.csdn.net/winter2121/article/details/79849472
https://nanti.jisuanke.com/t/19979
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #include <set> 8 #include <map> 9 #include <list> 10 #include <stack> 11 #include <queue> 12 #include <vector> 13 #include <bitset> 14 #include <ext/rope> 15 #include <algorithm> 16 #include <iostream> 17 using namespace std; 18 #define ll long long 19 #define minv 1e-6 20 #define inf 1e9 21 #define pi 3.1415926536 22 #define nl 2.7182818284 23 const ll mod=1e9+7;//998244353 24 const int maxn=1e2+10; 25 26 bool vis[maxn]; 27 int cony[maxn],r[maxn][maxn],n; 28 29 bool dfs(int x) 30 { 31 int y; 32 for (y=1;y<=n;y++) 33 if (!vis[y] && r[x][y]) 34 { 35 vis[y]=1; 36 if (cony[y]==0 || dfs(cony[y])) 37 { 38 cony[y]=x; 39 return 1; 40 } 41 } 42 return 0; 43 } 44 45 int main() 46 { 47 int sum,t,m,i,j,k,x,y; 48 scanf("%d",&t); 49 while (t--) 50 { 51 scanf("%d%d",&n,&m); 52 memset(r,0,sizeof(r)); 53 for (i=1;i<=m;i++) 54 { 55 scanf("%d%d",&x,&y); 56 r[x][y]=1; 57 } 58 59 for (k=1;k<=n;k++) 60 for (i=1;i<=n;i++) 61 for (j=1;j<=n;j++) 62 r[i][j]|=r[i][k]&r[k][j]; 63 64 sum=n; 65 memset(cony,0,sizeof(cony)); 66 for (i=1;i<=n;i++) 67 { 68 memset(vis,0,sizeof(vis)); 69 sum-=dfs(i); 70 } 71 printf("%d\n",sum); 72 } 73 return 0; 74 }
另外:(copy from other)
最大匹配数:最大匹配的匹配边的数目
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立数(最大团):选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)
定理2:最大匹配数 = 最大独立数
定理3:最小路径覆盖数 = 顶点数 - 最大匹配数