POJ 1698 最大流

24 篇文章 0 订阅
18 篇文章 0 订阅

题意:一个演员,给你N部电影,每部电影必须在M周前完成,每部电影一周有固定的拍摄时间,这个演员一天只能拍一部,问这个演员能否拍所有的电影。

思路:这题可以用二分匹配,匈牙利算法搞,应该很快,我用了网络流,熟练一下模板。

建图方法。

S - MOVIE ,权值是电影的拍摄次数。

MOVIE - 天数 ,将MOVIE和能拍摄的天数连起来,权值是1。

天数 - T ,将所有天数和T连起来,权值是1,因为每天最多拍摄一次。 

这题WA了2次。原因是把Yes打成YES了,而且我居然花了半小时才DEBUG出来。。。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>

using namespace std;
#define Max 2005
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 1 << 30
int S,T ;
int Map[505][505] ;//把邻接表换成邻接矩阵了


int deep[Max] ;
int qe[Max * 100] ;
int dinic_bfs()
{
    mem(deep,-1) ;
    deep[S] = 0 ;
    int h = 0 ,t = 0 ;
    qe[h ++ ] = S ;
    while(h > t)
    {
        int tt = qe[t ++ ] ;
        for (int i = S ; i <= T ; i ++)
        {
            if(Map[tt][i] && deep[i] == -1)
            {
                deep[i] = deep[tt] + 1 ;
                qe[h ++ ] = i ;
            }
        }
    }
    return deep[T] != -1 ;
}

int dinic_dfs(int now ,int f)
{
    if(now == T)return f ;
    int flow = 0 ;
    for (int i = S ; i <= T ; i ++)
    {
        if(deep[i] == deep[now] + 1 && Map[now][i])
        {
            int mm = min(Map[now][i],f - flow) ;
            int nn = dinic_dfs(i , mm) ;
            flow += nn ;
            Map[now][i] -= nn ;
            Map[i][now] += nn ;
        }
    }
    if(!flow )deep[now] = -2 ;
    return flow ;
}
int dinic()
{
    int flow = 0 ;
    while(dinic_bfs())
    {
        flow += dinic_dfs(S,inf) ;
    }
    return flow ;
}


bool vis[10] ;
int main()
{
    int t ;
    cin >> t ;
    while( t -- )
    {
        int n ;
        cin >> n ;
        mem(Map,0) ;
        S = 0 ;T = 500 ;
        int sum = 0 ;
        for (int i = 1 ; i <= n ; i ++ )
        {
            mem(vis,0) ;
            for (int j = 1 ; j <= 7 ; j ++ )cin >> vis[j] ;
            int day ,week ;
            cin >> day >> week ;
            Map[S][i] = day ;//源点和电影连接
            sum += day ;
            for (int j = 0 ; j < week ; j ++ )
            {
                for (int k = 1 ; k <= 7 ; k ++ )
                {
                    int dd = n + k + (j ) * 7 ;
                    Map[dd][T] = 1 ;//天数和汇点连接
                    if(vis[k])
                    {
                        Map[i][dd] = 1 ;//电影和该电影能拍的天数连接
                    }
                }
            }
        }
        int ans = dinic() ;
        if(ans == sum)cout <<"Yes"<<endl;
        else cout <<"No"<<endl;
    }
    return 0 ;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值