# tioj 1253 砲打皮皮 https://tioj.ck.tp.edu.tw/problems/1253 * 一個強者物質能消滅整列或整行,也就是一個x或y * 所以把皮皮的x, y座標互相連成二分圖,而目標就是把每條線都涵蓋到(也就是最小點覆蓋) * 假設有(a, b), (a, c), (a, d)這些皮皮,這樣圖就是左邊的x=a連三條分別到y=b,c,d。所以如果選x=a,擇三條線都會覆蓋到(aka三個皮皮都消滅),成為最小點覆蓋。但如果選y=b,只有一條a - b的線被覆蓋到。 * 已知二分圖最大匹配=二分圖最小點覆蓋 ```cpp= #include <bits/stdc++.h> #define EB emplace_back #define vci vector<int> #define PII pair<int,int> #define F first #define S second #define rep(X, a,b) for(int X=a;X<b;++X) #define ALL(a) (a).begin(), (a).end() #define SZ(a) (int)(a).size() #define NL "\n" #define LL long long using namespace std; struct bpt{ vector<int> lg[1010]; int lm[1010], rm[1010], done[1010]; bool dfs(int v){ done[v]=1; for(auto a:lg[v]){ if(rm[a]==-1 || (!done[rm[a]] && dfs(rm[a]))){ lm[v]=a; rm[a]=v; return 1; } } return 0; } LL matching(int n){ LL ans=0; memset(lm, -1, sizeof(lm)); memset(rm, -1, sizeof(rm)); rep(i,1,n+1){ if(lg[i].empty()) continue; memset(done, 0, sizeof(done)); if(dfs(i)) ans++; } return ans; } }; int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); LL n, k, cnt=0; while(cin>>n>>k){ if(n==0) break; bpt pp; int a, b; rep(i,0,k){ cin>>a>>b; pp.lg[a].push_back(b); } cout<<"Case #"<<++cnt<<":"<<pp.matching(n)<<NL; } } ```