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
- HDU 4560解题报告
- HDU 3342 解题报告
- HDU 3336 解题报告
- HDU 3335 解题报告
- hdu 2516解题报告
- hdu 1004解题报告
- hdu 2139解题报告
- hdu 1019解题报告
- hdu 1064 解题报告
- HDU 1113 解题报告
- hdu 1068 解题报告
- HDU:2050解题报告
- hdu 4001解题报告
- hdu 1005解题报告
- HDU解题报告--1003
- HDU解题报告--1004
- HDU解题报告--1005
- HDU 1005 解题报告
- alamofire语法已经变化 3.1.5版本
- 排序算法总结
- 张正友标定论文翻译(2)
- 找出升序数组中和为给定值的两个数字
- iPhone屏幕像素 分辨率 xcode中的逻辑宽高的介绍以及strcut与class的区别
- HDU 4560解题报告
- 华为机试题:整数排序
- HDU3371 并查集与最小生成树(判断有无生成树)
- segfault at xxx rip xxx rsp xxx error 4
- WebKit之V8编写简单demon
- C语言 求一个数列的前n项之和,保留两位小数。
- win7下安装/卸载VirtualBox时出错
- MFC下ADO访问ACCESS插入日期
- cocos2d-x核心概念(四)——动作,动画