您的位置:首页 > 其它

POJ 1698 Alice's Chance

2010-11-20 00:15 309 查看
构图很重要。。。

每部电影作为一个源点,然后把每个星期的每一天看成一个点,每个点只可以贡献一个工作日,即出边(到汇点)的容量只能是1,而入边的容量也为1,只要某部电影可以在该天工作,就可能选择该天,即该部电影对应的点到该个工作日对应的点之间连一条线,最后,添加一个超级源点,它到每部电影对于的点之间的容量为该部电影需要的工作日(不能为无穷大)

一开始把工作日与电影的关系对应反了,让工作日去找电影,这样节点个数就有50×20×7,太多了,实际上,电影在每一个工作日上都重复一次,何不让电影去找工作日呢?这样每个电影节点就只会出现一次了

代码:

#include<iostream>
using namespace std;
#define inf 999999
int f[375][375],cap[375][375];
int pre[375],rc[375],q[375],w[51][8];
int n,m,ans;
bool bfs()
{
int i,j,head=0,tail=1;
memset(rc,0,sizeof(rc));
pre[0]=-1;
rc[0]=9999999;
q[tail]=0;
while(head<tail)
{
i=q[++head];
for(j=1;j<=n+m*7+1;j++)
{
if(cap[i][j]>f[i][j]&&!rc[j])
{
rc[j]=rc[i];
if(cap[i][j]-f[i][j]<rc[j])
rc[j]=cap[i][j]-f[i][j];
pre[j]=i;
q[++tail]=j;
if(j==n+m*7+1)
return true;
}
}
}
return false;
}
void update()
{
for(int i=n+m*7+1;i!=0;i=pre[i])
{
f[pre[i]][i]+=rc[n+m*7+1];
f[i][pre[i]]=-f[pre[i]][i];
}
ans+=rc[n+m*7+1];
}
void EK()
{
while(bfs())
update();
}
int main()
{
int i,j,k,deadline[51],test,sum,day;
cin>>test;
while(test--)
{
scanf("%d",&n);
memset(f,0,sizeof(f));
memset(cap,0,sizeof(cap));
m=-1;
sum=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=7;j++)
scanf("%d",&w[i][j]);
scanf("%d%d",&day,&deadline[i]);
cap[0][i]=day;
if(deadline[i]>m)
m=deadline[i];
sum+=day;
}
for(i=1;i<=n;i++)
for(j=1;j<=deadline[i];j++)
{
for(k=1;k<=7;k++)
{
if(w[i][k])
{
cap[i][n+(j-1)*7+k]+=1;
cap[n+(j-1)*7+k][n+m*7+1]=1;
}
}
}
ans=0;
EK();
if(ans==sum)
printf("Yes/n");
else
printf("No/n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: