Konig 定理
二分图最小点覆盖包含的点数等于二分图最大匹配包含的边数
POJ 1325
有两台机器A,B,及N个任务,每台机器有M种不同的模式。
对于每个任务 i ,给定两正整数ai 和bi 表示若在A上执行,需切换到模式ai,否则bi。
任务可以随意顺序执行,每台机器转换模式就要重启一次。求怎样分配任务可以使重启次数最少。
二分图最小覆盖的模型特点是:每条边有2个端点,二者至少选择一个。正好就是此题的模型。
需要注意的是,初始状态下机器是mode 0 ,因此加边的时候不要把0加进去。
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 998244353 #define moD 1000000003 #define pii pair<ll,int> #define eps 1e-7 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second #define pb push_back const int maxn = 105; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; typedef unsigned long long ull; using namespace std; int e[220][220]; int n, m; int vis[220], match[220]; int x, y, k; bool dfs(int x) { for (int i = 1; i <= y; i++) { if (e[x][i]) { if (vis[i]) continue; vis[i] = 1; if (!match[i] || dfs(match[i])) { match[i] = x; return true; } } } return false; } int Match() { int cnt = 0; memset(match, 0, sizeof match); for (int i = 1; i <= x; i++) { memset(vis, 0, sizeof vis); if (dfs(i)) cnt++; } return cnt; } int main() { while (scanf("%d", &x), x) { scanf("%d%d", &y, &k); memset(vis, 0, sizeof vis); memset(e, 0, sizeof e); int a, b, c; for (int i = 0; i < k; i++) { scanf("%d%d%d", &a, &b, &c); if (!b || !c) continue; b++; c++; e[b][c] = 1; } printf("%d ", Match()); } }