poj 1698 Alice's Chance http://poj.org/problem?id=1698

本文介绍了一个基于最大流算法解决电影演员参演多个电影时的调度问题。通过构建网络图并利用Edmonds-Karp算法求解最大流,判断演员是否能在限定时间内完成所有电影的拍摄。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:Alice要参演电影,但同时有几个电影,Alice想都参演,问能否都能演上;输入T个样例,每个样例有n个电影,然后输入一星期的哪几天可以演这个电影,然后是电影需要d天,要在w星期内完成;

题解:最大流问题,添加源点s=0,汇点t=399,对于编号从1……n编号,将源点和电影i相连,容量置为该部电影拍摄完成需要的天数,将电影i和其特定的拍摄日期相连(将第k星期的星期j编号为n+7*k+j),该边的容量置为1,然后将该日期和汇点相连,容量也是置为1,再对构建的网络求解最大流,如果该最大流等于所有电影拍摄完成需要的天数,那么输出"Yes",否则输出"No".

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define maxn 400
#define INF 0xffffff
int cap[maxn][maxn],flow[maxn][maxn],res[maxn],pre[maxn];
int n,d[25],w[25],f[25][10];
int Edmonds_Karp(int start,int end)
{
    int maxflow=0;
    memset(flow,0,sizeof(flow));
    memset(pre,0,sizeof(pre));
    queue<int> q;
    while(true)
    {
        memset(res,0,sizeof(res));
        res[start]=INF;
        q.push(start);
        while(!q.empty()) //BFS寻找增广路
        {
            int u=q.front();
            q.pop();
            for(int v=1;v<=end;v++)
                if(!res[v]&&cap[u][v]>flow[u][v])
                {
                    res[v]=min(res[u],cap[u][v]-flow[u][v]);//start-v路径上的最小残量
                    //记录v的父亲,并加入队列中
                    pre[v]=u;
                    q.push(v);
                }
        }
        if(res[end]==0) return maxflow;//无法继续更新最大流量,则当前流已经是最大流
        for(int u=end;u!=start;u=pre[u])//从汇点往回走
        {
            flow[pre[u]][u]+=res[end];//更新正向流
            flow[u][pre[u]]-=res[end];//更新反向流
        }
        maxflow+=res[end]; //更新从s流出的总流量
    }
    return maxflow;
}
int main()
{
    int test;
    scanf("%d",&test);
    while(test--)
    {
        memset(cap,0,sizeof(cap));
        int sum=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=7;j++)
            {
                scanf("%d",&f[i][j]);
            }
            scanf("%d%d",&d[i],&w[i]);
            sum+=d[i];
        }
        for(int i=1;i<=n;i++)
        {
            cap[0][i]=d[i];
        }
        for(int i=21;i<=398;i++)
        {
            cap[i][399]=1;
        }
        for(int i=1;i<=n;i++)
        {
            for(int k=0;k<w[i];k++)
            {
                for(int j=1;j<=7;j++)
                {
                    cap[i][20+k*7+j]=f[i][j];
                }
            }
        }
        if(sum==Edmonds_Karp(0,399))
        printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值