1305: [CQOI2009]dance跳舞
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 3822 Solved: 1631
[ Submit][ Status][ Discuss]
Description
一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?
Input
第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。
Output
仅一个数,即舞曲数目的最大值。
Sample Input
3 0
YYY
YYY
YYY
YYY
YYY
YYY
Sample Output
3
HINT
N<=50 K<=30
Source
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; typedef long long LL; const int maxn = 50 * 10; const int maxm = maxn * maxn * 10; const int INF = 2147483647; struct data{ int to,cap,flow; }e[maxm]; vector<int> G[maxn]; int ans,n,m,k,tot,s,t,tote = -1; int cur[maxn],dis[maxn],Q[maxn]; int lx[maxn],ox[maxn],ly[maxn],oy[maxn]; int id[maxm],now; inline LL getint() { LL ret = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar(); return ret; } inline bool bfs() { memset(dis,-1,sizeof(dis)); memset(cur,0,sizeof(cur)); int head = 0,tail = 0; dis[Q[++tail] = s] = 0; while (head < tail) { int u = Q[++head]; for (int i = 0; i < G[u].size(); i++) { data E = e[G[u][i]]; if (dis[E.to] != -1 || E.flow == E.cap) continue; dis[Q[++tail] = E.to] = dis[u] + 1; } } return dis[t] != -1; } inline int dinic(int u,int a) { if (u == t || !a) return a; int flow = 0; for (int &i = cur[u]; i < G[u].size(); i++) { data &E = e[G[u][i]]; if (E.flow == E.cap || dis[E.to] != dis[u] + 1) continue; int f = dinic(E.to,min(a,E.cap - E.flow)); if (!f) continue; E.flow += f; flow += f; e[G[u][i] ^ 1].flow -= f; a -= f; if (!a) break; } return flow; } inline void add(int u,int v,int cap) { e[++tote] = (data){v,cap,0}; G[u].push_back(tote); e[++tote] = (data){u,cap,cap}; G[v].push_back(tote); } inline char getcom() { char c = getchar(); while (c != 'Y' && c != 'N') c = getchar(); return c; } int main() { n = getint(); k = getint(); s = ++tot; t = ++tot; for (int i = 1; i <= n; i++) { int tmp = ++tot; add(s,tmp,0); id[++now] = tote - 1; add(tmp,lx[i] = ++tot,k); add(tmp,ox[i] = ++tot,INF); tmp = ++tot; add(tmp,t,0); id[++now] = tote - 1; add(ly[i] = ++tot,tmp,k); add(oy[i] = ++tot,tmp,INF); } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { char c = getcom(); if (c == 'Y') add(ox[i],oy[j],1); else add(lx[i],ly[j],1); } for (int i = 1; i <= n + 1; i++) { for (int j = 1; j <= now; j++) { e[id[j]].cap++; e[id[j] ^ 1].cap++; e[id[j] ^ 1].flow++; } int ans = 0; while (bfs()) ans += dinic(s,INF); int flag = 0; for (int j = 1; j <= now; j++) if (e[id[j]].flow < e[id[j]].cap) flag = 1; if (flag) { printf("%d",i - 1); break; } } return 0; }