poj 1698

来源:互联网 发布:阿里办公软件 编辑:程序博客网 时间:2024/06/07 23:06

题目概述

alice接了N部电影的拍摄工作,所有电影在同一天开工,每周只有固定几天拍,其余时间不拍,电影必须在w周内拍完,alice至少需要去拍d天,问alice能否完成所有电影拍摄
alice每天只能去拍一部电影,每周第一天是周日

时限

1000ms/3000ms

输入

第一行整数times,其后times组数据,每组数据第一行整数N,其后N行,每行九个整数,前七个只有1或0,1表示每周这一天可拍,0反之,其后是d,w

限制

1<=times<=20;1<=N<=20;1<=d<=50;1<=w<=50

输出

每行一个字符串,若能完成所有拍摄,为Yes,否则为No

样例输入

2
2
0 1 0 1 0 1 0 9 3
0 1 1 1 0 0 0 6 4
2
0 1 0 1 0 1 0 9 4
0 1 1 1 0 0 0 6 2

样例输出

Yes
No

讨论

图论,应该算是二分图,但还没看到那部分,只能先用网络流处理,利用Isap+gap优化,主要还是构图,将每一天看做一个节点,编号0到349,因为最多50周,电影也看做节点,编号350到369,然后虚构一个源点370,汇点371,从源点出发流向每部电影,流量就是需要拍摄的天数,从每部电影到拍摄周内拍摄的那些天,流量是1,因为每天只能拍一部,同理这些天都连接到汇点,流量也是1,如此,若能全拍,则最大流量应为所有电影需要拍摄天数和
实现层次上,isap的gap优化不能垄断所有return,因为程序可能不从gap优化结束,而是从原始while判断条件结束,虽然有点不可思议,但确实如此,所有层次都有剩余,但源点已经被排除了,不再有最短路,程序结束,着实不知道如何发生的,好在并不难修改,给fun函数添加正常return出口,而gap优化改为break出while循环,这样就能照顾到所有情况了,这样说有点抽象,代码里会体现

题解状态

728K,16MS,C++,1777B

题解代码

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define INF 0x3f3f3f3f#define MAXN 374#define memset0(a) memset(a,0,sizeof(a))int N, S = 370, T = 371;//电影总数 以及虚构的源点汇点 这两点编号是固定的int R[MAXN][MAXN], dis[MAXN], from[MAXN], gap[MAXN];//isap四大数组 残量矩阵 层次 父节点编号 每个层次的节点数bool mk[7];//marked 用于将每周拍摄时间进行构图queue<int>q;//bfs辅助队bool fun(){    int sum = 0;//所有电影合计拍摄天数    for (int p = 0; p < N; p++) {        for (int i = 0; i < 7; i++)            scanf("%d", &mk[i]);//input        int d, w;//拍摄需求天数 拍摄周数        scanf("%d%d", &d, &w);//input        sum += d;        R[S][p + 350] = d;//将源点与电影连接 残量是需求天数        for (int i = 0; i < 7; i++) {//完成电影到每天再到汇点的构图            if (!mk[i])//这天不拍 直接跳过                continue;            for (int u = 0; u < w; u++)                R[p + 350][i + 7 * u] = R[i + 7 * u][T] = 1;//将电影与拍摄周内拍摄日相连 拍摄日再连到汇点 残量都是1        }    }    N = 372;//既然汇点是371 那么N就是372了 虽然有点浪费 但好在数据规模小    for (int p = 0; p < N; p++)//初始化层次数组 不能直接用0 这点在poj 1273里被卡了好几次 因为0在N范围内 后面可能会被视为可行边        dis[p] = N;//初始化为N就足矣 因为在范围内的两点 最远不过N-1的层次差    dis[T] = 0;//汇点到自己是0层次 下面是bfs 这些都是一样的    gap[0]++;    q.push(T);    while (!q.empty()) {        int a = q.front();        q.pop();        for (int p = 0; p < N; p++)            if (dis[p] == N&&R[p][a]) {                q.push(p);                dis[p] = dis[a] + 1;                gap[dis[p]]++;            }    }    int most = 0, cur = S, flow = INF;//下面是isap算法主体    while (dis[S] < N) {        int p;        for (p = 0; p < N && (!R[cur][p] || dis[cur] != dis[p] + 1); p++);        if (p != N) {            from[p] = cur;            flow = min(flow, R[cur][p]);            cur = p;            if (cur == T) {                most += flow;                while (cur != S) {                    p = from[cur];                    R[p][cur] -= flow;                    R[cur][p] += flow;                    cur = p;                }                flow = 1;            }        }        else {            if (!--gap[dis[cur]])                break;            dis[cur] = N;            for (int p = 0; p < N; p++)                if (R[cur][p] && dis[cur] > dis[p] + 1)                    dis[cur] = dis[p] + 1;            gap[dis[cur]]++;            if (cur != S)                cur = from[cur];        }    }    return most == sum;//算法现在有了正常的出口 没有这行结果必然会错}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    int times;    scanf("%d", &times);//input    while (times--) {        scanf("%d", &N);//input        if (fun())            printf("Yes\n")//output;        else            printf("No\n");//output        memset0(R);        memset0(gap);//dis有初始化 from会被覆盖 这两个需要初始化    }}

EOF

0 0
原创粉丝点击