POJ 1698 Alice's Chance
题目:Alice 要拍电影,每一天只能参与一部电影的拍摄,每一部电影只能在
典型的二分图多重匹配,这里用了最大流的 dinic 算法。构图:源点向每部电影流容量为
一开始用了多路增广忘了把流量为零的 d 设为 -1……悲剧……TLE 了。
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int MAXV = 520, FILM = 400, MAXE = 15000, INF = 0x3f3f3f3f;
struct edge{
int to, cap, next;
edge(){};
edge(int to_, int cap_, int next_):to(to_), cap(cap_), next(next_){};
} es[MAXE];
int head[MAXV], d[MAXV], que[MAXV], tot, tmp[8];
void init(){
memset(head, -1, sizeof(head));
tot = 0;
}
inline void add2(const int &a, const int &b, const int &cap){
// printf("%d---%d: %d\n", a, b, cap);
es[tot] = edge(b, cap, head[a]); head[a] = tot++;
es[tot] = edge(a, 0, head[b]); head[b] = tot++;
}
bool bfs(int s, int t){
memset(d, -1, sizeof(d));
d[s] = 0;
int hh = 0, tt = 1;
que[0] = s;
while(hh < tt){
int u = que[hh++];
if(u == t)return true;
for(int i = head[u]; ~i; i = es[i].next){
int v = es[i].to;
if(d[v] == -1 && es[i].cap){
d[v] = d[u] + 1;
que[tt++] = v;
}
}
}
return false;
}
int dfs(int s, int t, int low){
if(s == t) return low;
int ret = 0;
for(int i = head[s]; ~i; i = es[i].next){
int v = es[i].to, f = es[i].cap;
if(d[v] == d[s] + 1 && f && (f = dfs(v, t, min(low - ret, f)))){
es[i].cap -= f;
es[i^1].cap += f;
ret += f; //多路增广
if(ret == low) break;
}
}
if(!ret) d[s] = -1; //这里剪枝非常重要
return ret;
}
int dinic(int s, int t){
int ans = 0;
while(bfs(s, t)){
ans += dfs(s, t, INF);
}
return ans;
}
int main(){
freopen("in.txt", "r", stdin);
int T, N, D, W;
scanf("%d", &T);
while(T--){
init();
int sum = 0, day = 0;
scanf("%d", &N);
for(int i = 0; i < N; ++i){
for(int j = 1; j <= 7; ++j) scanf("%d", &tmp[j]);
scanf("%d%d", &D, &W);
day = max(day, W);
add2(0, FILM + i, D);
sum += D;
for(int w = 0; w < W; ++w){
for(int j = 1; j <= 7; ++j){
if(tmp[j]) add2(FILM + i, w * 7 + j, 1);
}
}
}
for(int i = day * 7; i > 0; --i){
add2(i, 500, 1);
}
int ans = dinic(0, 500);
if(ans == sum) printf("Yes\n");
else printf("No\n");
}
return 0;
}
退役