HDU 4560解题报告

来源:互联网 发布:淘宝中的延长收货 编辑:程序博客网 时间:2024/04/25 21:05

根据题目的意思,我们设比赛场次为c,二分这个场次,然后建边跑网络流,看看最后流量能不能等于n*c即可。
建边是最难得地方。。
源点s,汇点t
因为每个人要演出c次,那么s向每个歌手连一条容量为c的边。
把每个流派拆成两个点k, k’点分别表示擅长和不擅长的点
那么每个歌手向k和k’都连一条容量为1的边,表示每场次演唱一首歌。
然后k’点向k点连一条容量为C(限制)的边,表示整个演唱场次下来,第k流派的最大观众容忍度。
然后k向汇点连一条容量为c的边

/*纳兰性德 -清《长相思·山一程》山一程,水一程,身向榆关那畔行,夜深千帐灯。风一更,雪一更,聒碎乡心梦不成,故园无此声。*///  Created by Matrix on 2016-02-02//  Copyright (c) 2015 Matrix. All rights reserved.//////#pragma comment(linker, "/STACK:102400000,102400000")#include <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <sstream>#include <set>#include <vector>#include <stack>#define ALL(x) x.begin(), x.end()#define INS(x) inserter(x, x,begin())#define ll long long#define CLR(x) memset(x, 0, sizeof x)using namespace std;const int inf = 0x3f3f3f3f;const int MOD = 1e9 + 7;const int maxn = 2e4 + 10;const int maxv = 1e3 + 10;const double eps = 1e-9;int n, m, l, k;int head[maxv], nxt[maxn], cap[maxn], pnt[maxn], cnt;void add_edge(int u, int v, int c) {    pnt[cnt] = v;    cap[cnt] = c;    nxt[cnt] = head[u];    head[u] = cnt++;}void add(int u, int v, int c) {    add_edge(u, v, c);    add_edge(v, u, 0);}int level[maxv], cur[maxv];bool bfs(int s, int t) {    memset(level, -1, sizeof level);    queue <int> que;    level[s] = 0;    que.push(s);    while(que.size() && level[t] == -1) {        int u = que.front(); que.pop();        for(int i = head[u]; ~i; i = nxt[i]) {            int v = pnt[i];            if(cap[i] > 0 && level[v] == -1) {                level[v] = level[u] + 1;                que.push(v);            }        }    }    return level[t] != -1;}int dfs(int u, int t, int f) {    if(u == t) return f;    int left = f;    for(int i = cur[u]; ~i; i = nxt[i]) {        int v = pnt[i];        if(cap[i] > 0 && level[v] == level[u] + 1) {            int d = dfs(v, t, min(left, cap[i]));            cap[i] -= d;            cap[i^1] += d;            cur[u] = i; //当前弧优化            left -= d; //多路增广            if(!left) return f;        }    }    level[u] = -1;    return f - left;}int dinic(int st, int ed) {    int ans = 0;    while(bfs(st, ed)) {        for(int i = st; i <= ed; i++) cur[i] = head[i];        ans += dfs(st, ed, inf);    }    return ans;}int mp[maxv][maxv];int st, ed;bool check(int c) {    memset(head, -1, sizeof head);    cnt = 0;    for(int i = 1; i <= n; i++) {        add(st, i, c);        for(int j = 1; j <= m; j++) {            if(mp[i][j]) {                add(i, j + n, 1);            }            else add(i, j + n + m, 1);        }    }    for(int i = n + 1; i <= n + m; i++) {        add(i + m, i, k);        add(i, ed, c);    }    return dinic(st, ed) >= n * c;}int main() {#ifdef LOCAL    freopen("in.txt", "r", stdin);//  freopen("out.txt","w",stdout);#endif    int cas = 0, T;    scanf("%d", &T);    while(T--) {        CLR(mp);        scanf("%d%d%d%d", &n, &m, &l, &k);        for(int i = 1; i <= l; i++) {            int u, v;            scanf("%d%d", &u, &v);            mp[u][v] = 1;        }        st = 0, ed = n + m * 2 + 1;        int l = 0, r = m;        while(l <= r) {            int mid = (l + r) / 2;            if(check(mid)) l = mid + 1;            else r = mid - 1;        }        printf("Case %d: %d\n", ++cas, l - 1);    }    return 0;}
0 0
原创粉丝点击