標籤:blog os 2014 io for re
行做x集,列做y集,1就給該行該列連一條邊,輸出最大匹配邊即可
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<vector>#include<set>using namespace std;#define N 105int lef[N], pn;//lef[v]表示Y集的點v 當前串連的點 , pn為x點集的點數bool T[N]; //T[u] 表示Y集 u 是否已串連X集vector<int>G[N]; //匹配邊 G[X集].push_back(Y集) 注意G 初始化bool match(int x){ // x和Y集 匹配 返回x點是否匹配成功for(int i=0; i<G[x].size(); i++){int v = G[x][i];if(!T[v]){T[v] = true;if(lef[v] == -1 || match( lef[v] )) //match(lef[v]) : 原本串連v的X集點 lef[v] 能不能和別人連,如果能 則v這個點就空出來和x連{lef[v] = x;return true;}}}return false;}int solve(){int ans = 0;memset(lef, -1, sizeof(lef));for(int i = 1; i<= pn; i++)//X集匹配,X集點標號從 1-pn 匹配邊是G[左點].size(){memset(T, 0, sizeof(T));if( match( i ) ) ans++;}return ans;}int n, m;int mp[N][N];int main(){ int i, j; while(scanf("%d",&n), n){ scanf("%d",&m); for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) scanf("%d",&mp[i][j]); for(i = 1; i <= n; i++) G[i].clear(); pn = n; for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) if(mp[i][j]) G[i].push_back(j); printf("%d\n", solve()); } return 0;}