您的位置:首页 > 其它

POJ 1698 Alice's Chance

2010-02-03 16:15 295 查看
/* 一个演员很想参加film,但是一天只能参加一项,且每项必须在规定的几个星期内参加规定的天数,求演员是否能全部完成所有的film档期。 可以考虑用网络流做,加源汇点,如果film_i 和week_i_day_j天有联系,那么就连一条INF边,源点到film_i连一条day_i边,各个星期的天数到汇点连一条1边,求最大流是否和总天数相等。最大流用isap就可以了,非常快。 */

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <queue>
using namespace std;

#define INF 0x7ffffff
#define MAXN 500
#define MAXE 20000

struct Edge{
int next,pair;
int v,cap,flow;
}edge[MAXE];
int net[MAXN];
int nv,ne,s,t,index,max_week,sum;
void init()
{
index = 0;
memset(net,-1,sizeof(net));
s = 0; // start position
max_week = -1;
sum = 0;
}
void add_edge(const int& u,const int& v,const int& val)
{
edge[index].next = net[u];
net[u] = index;
edge[index].v = v;
edge[index].cap = val;
edge[index].flow = 0;
edge[index].pair = index + 1;
++index;
edge[index].next = net[v];
net[v] = index;
edge[index].v = u;
edge[index].cap = 0;
edge[index].flow = 0;
edge[index].pair = index - 1;
++index;
}
int ISAP()
{
int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
int cur_flow,max_flow,u,tmp,neck,i;
memset(dist,0,sizeof(dist));
memset(numb,0,sizeof(numb));
for(i = 1 ; i <= nv ; ++i)
curedge[i] = net[i];
numb[nv] = nv;
max_flow = 0;
u = s;
while(dist[s] < nv){
if(u == t){
cur_flow = INF+1;
for(i = s; i != t;i = edge[curedge[i]].v)
if(cur_flow > edge[curedge[i]].cap){
neck = i;
cur_flow = edge[curedge[i]].cap;
}
for(i = s; i != t; i = edge[curedge[i]].v)
{
tmp = curedge[i];
edge[tmp].cap -= cur_flow;
edge[tmp].flow += cur_flow;
tmp = edge[tmp].pair;
edge[tmp].cap += cur_flow;
edge[tmp].flow -= cur_flow;
}
max_flow += cur_flow;
u = neck;
}
for(i = curedge[u]; i != -1; i = edge[i].next)
if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)
break;
if(i != -1){
curedge[u] = i;
pre[edge[i].v] = u;
u = edge[i].v;
}else{
if(0 == --numb[dist[u]]) break;
curedge[u] = net[u];
for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)
if(edge[i].cap > 0)
tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
dist[u] = tmp + 1;
++numb[dist[u]];
if(u != s) u = pre[u];
}
}
return max_flow;
}

int main()
{
int i,j,k,h,time,ans,n,work[7],day,week;
scanf("%d",&time);
while(time--)
{
init();
scanf("%d",&n);
for(i = 1; i <= n; ++i)
{
for(j = 0;j < 7; ++j)
scanf("%d",&work[j]);
scanf("%d%d",&day,&week);
add_edge(s,i,day);
for(j = 0;j < week; ++j)
for(k = 0;k < 7; ++k)
if(work[k]) // can do
add_edge(i,n+j*7+k+1,INF);
max_week = max_week>week?max_week:week;
sum += day;
}
t = n+max_week*7+1;
nv = t + 1;
for(i = 0;i < max_week; ++i )
for(j = 1;j <= 7; ++j)
add_edge(n+i*7+j,t,1);
ans = ISAP();
if(sum == ans)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: