算法:POJ 3683 Priest John's Busiest Day(2-SAT + 拓扑输出方案)

【题目大意】

有个小镇上有n对夫妻要举办婚礼,每队夫妻都要请镇上的牧师举行一个仪式,但 是镇上只有一个牧师,牧师一次只能为一对夫妻做仪式。

已知每队夫妻的婚礼的起始t1和结束的时 间t2, 他们举办仪式的时间是d,仪式只能在婚礼开始的前d时间举行或者在结束之前的d内举行。问牧师能 不能合理安排,使得每对夫妻都能举办仪式?

【思路】

对于每一对夫妻,他们要么在开始时 做仪式,要么在结束时做仪式,所以是2-SAT模型。

这题要输出任一个方案,研究了好几个小时。。 。

【代码】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define WHITE -1
#define RED 1
#define BLUE 0
using namespace std;  

typedef long long int64;  

const int MAXN = 1010;
const int VN   = MAXN*2;
const int EN   = 1000010;
int n;  

struct Couple{
    int  d;
    int  t1, t2;
}arr[MAXN];  

struct Edge{
    int u, v, next;
};  

void time_out(int t, int d){
    printf("%02d:%02d %02d:%02d\n", t/60, t%60, (t+d)/60, (t+d)%60);
}  

struct Graph{
    int size;
    int head[VN];
    Edge E[EN];  

    void init(){
        size = 0;
        memset(head, -1, sizeof(head));
    }  

    void addEdge(int u, int v){
        E[size].u = u;
        E[size].v = v;
        E[size].next = head[u];
        head[u] = size++;
    }
}g, g2; //g为原图, g2为新图  

class Two_SAT{
public:
    bool check(const Graph& g, const int n){
        scc(g, 2*n);
        for(int i=0; i<n; ++i)
            if(belong[i] == belong[i+n])
                return false;
        return true;
    }  

    void toposort(const Graph&g, Graph& g1, const int n){
        g1.init();
        memset(indeg, 0, sizeof(indeg));
        for(int i=0; i<n; ++i){
            opp[belong[i]] = belong[i+n];
            opp[belong[i+n]] = belong[i];
        }  

        for(int e=0; e<g.size; ++e){
            int u = belong[g.E[e].u];
            int v = belong[g.E[e].v];
            if(u == v) continue;
            ++indeg[u];
            g1.addEdge(v, u);
        }  

        queue<int>que;
        memset(color, WHITE, sizeof(color));
        for(int i=1; i<=bcnt; ++i)
            if(!indeg[i])
                que.push(i);  

        int* head = g1.head;
        Edge* E   = g1.E;  

        while(!que.empty()){
            int u = que.front();
            que.pop();
            if(color[u] != WHITE) continue;
            color[u] = RED;
            color[opp[u]] = BLUE;  

            for(int e=head[u]; e!=-1; e=E[e].next){
                int v = E[e].v;
                if(--indeg[v] == 0){
                    que.push(v);
                }
            }
        }  

        for(int i=0; i<n; ++i){
            if(color[belong[i]]==RED){
                time_out(arr[i].t1, arr[i].d);
            }else{
                time_out(arr[i].t2-arr[i].d, arr[i].d);
            }
        }  

    }  

private:
    void tarjan(const Graph& g, const int u){
        int v;
        DFN[u] = low[u] = ++idx;
        sta[top++] = u;
        instack[u] = true;  

        for(int e=g.head[u]; e!=-1; e=g.E[e].next){
            v = g.E[e].v;
            if(DFN[v] == -1){
                tarjan(g, v);
                low[u] = min(low[u], low[v]);
            }else if(instack[v]){
                low[u] = min(low[u], DFN[v]);
            }
        }  

        if(DFN[u] == low[u]){
            ++bcnt;
            do{
                v = sta[--top];
                instack[v] = false;
                belong[v] = bcnt;
            }while(u != v);
        }
    }  

    void scc(const Graph&g, const int n){
        idx = top = bcnt = 0;
        memset(DFN, -1, sizeof(DFN));
        memset(instack, 0, sizeof(instack));
        for(int i=0; i<n; ++i)
            if(DFN[i] == -1)
                tarjan(g, i);
    }  

private:
    int idx, top, bcnt;
    int DFN[VN];
    int low[VN];
    int belong[VN];
    int sta[VN];
    bool instack[VN];  

    // 求方案
    int indeg[VN];
    int color[VN];
    int opp[VN];  

}sat;  

bool isCross(int a1, int b1, int a2, int b2){
    return !(a2>=b1 || a1>=b2);
}  

int main(){  

    int a, b;
    while(~scanf("%d", &n)){  

        g.init();
        for(int i=0; i<n; ++i){
            scanf("%d:%d",&a, &b);
            arr[i].t1 = a*60+b;
            scanf("%d:%d",&a, &b);
            arr[i].t2 = a*60+b;
            scanf("%d", &arr[i].d);
        }  

        for(int i=0; i<n; ++i){
            for(int j=i+1; j<n; ++j){
                const Couple& a=arr[i];
                const Couple& b=arr[j];
                if(isCross(a.t1, a.t1+a.d, b.t1, b.t1+b.d)){
                    g.addEdge(i, j+n);
                    g.addEdge(j, i+n);
                }
                if(isCross(a.t1, a.t1+a.d, b.t2-b.d, b.t2)){
                    g.addEdge(i, j);
                    g.addEdge(j, i+n);
                }
                if(isCross(a.t2-a.d, a.t2, b.t1, b.t1+b.d)){
                    g.addEdge(i+n, j+n);
                    g.addEdge(j, i);
                }
                if(isCross(a.t2-a.d, a.t2, b.t2-b.d, b.t2)){
                    g.addEdge(i+n, j);
                    g.addEdge(j+n, i);
                }
            }
        }  

        if(!sat.check(g, n)){
            puts("NO");
        }else{
            puts("YES");
            sat.toposort(g,g2,n);
        }  

    }  

    return 0;
}

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, include
, const
, arcengine 拓扑 输出
, head
, size
d3.js做网络拓扑图
busiest、find busiest group、findbusiestgroup、busiest airport、73683部队,以便于您获取更多的相关知识。

时间: 2024-11-17 00:33:48

算法:POJ 3683 Priest John's Busiest Day(2-SAT + 拓扑输出方案)的相关文章

数据结构和算法17 之拓扑排序

  这一节我们学习一个新的排序算法,准确的来说,应该叫"有向图的拓扑排序".所谓有向图,就是A->B,但是B不能到A.与无向图的区别是,它的边在邻接矩阵里只有一项(友情提示:如果对图这种数据结构部不太了解的话,可以先看一下这篇博文:数据结构和算法之 无向图.因为拓扑排序是基于图这种数据结构的). 有向图的邻接矩阵如下表所示:   A B C A 0 1 1 B 0 0 1 C 0 0 0         所以针对前面讨论的无向图,邻接矩阵的上下三角是对称的,有一半信息是冗余的.而

Hello World 程序的起源与历史

这是一个最著名的程序.对每一位程序员来说,这个程序几乎是每一门编程语言中的第一个示例程序.那么,这个著名的程序究竟从何而来呢? 实际上,这个程序的功能只是告知计算机显示 Hello World 这句话.传统意义上,程序员一般用这个程序测试一种新的系统或编程语言.对程序员来说,看到这两个单词显示在电脑屏幕上,往往表示他们的代码已经能够编 译.装载以及正常运行了,这个输出结果就是为了证明这一点. 这个测试程序在一定程度上具有特殊的象征意义.在过去的几十年间,这个程序已经渐渐地演化成为了一个久负盛名的

Hello World程序的起源与历史

这是一个最著名的程序.对每一位程序员来说,这个程序几乎是每一门编程语言中的第一个示例程序.那么,这个著名的程序究竟从何而来呢? 实际上,这个程序的功能只是告知计算机显示 Hello World 这句话.传统意义上,程序员一般用这个程序测试一种新的系统或编程语言.对程序员来说,看到这两个单词显示在电脑屏幕上,往往表示他们的代码已经能够编译.装载以及正常运行了,这个输出结果就是为了证明这一点. 这个测试程序在一定程度上具有特殊的象征意义.在过去的几十年间,这个程序已经渐渐地演化成为了一个久负盛名的传

怎么通过c#编程对DEM进行随机采样、规则采样啊

问题描述 怎么通过c#编程对DEM进行随机采样.规则采样啊求思路和代码啊 解决方案 解决方案二:一空间数据压缩算法1基于矢量的压缩算法2基于栅格的压缩算法二空间数据内插算法1点的内插算法2区域内插算法3采样点曲线拟合三空间数据转换算法1矢量数据向栅格数据转换2栅格数据向矢量数据转换3TIN向规则格网DEM转换四空间数据误差分析算法1属性误差的分析算法2位置误差分析算法五多边形自动生成与裁剪算法1多边形性质及有关处理2弧-弧拓扑生成算法3多边形自动生成算法4多边形图裁剪算法六TIN的构建算法1基于

DARPA如何定义网络作战空间

在PLANX项目的BAA中描述了概念性的网络作战空间,整个项目以该定义为基础来打造网络战平台网络空间已经成为继陆地海洋天空太空之外的第五维战场,受到了越来越多的关注,各国纷纷建立自己的网络作战部队,为网络战争进行准备. 进行网络战争离不开网络作战空间,对于网络作战空间如何描述.网络战场应该如何构建,美国国防部先进研究项局(DARPA)PLAN X项目提供了一个很好的参考.关于整个项目的系统细节我们不得而知,在本文中主要通过PLAN X项目的 BAA中关于网络作战空间的定义和项目范围来窥测网络作战

算法:poj 1155 TELE (树形背包dp)

题意 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结 构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从 转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号 的费用总和. 现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪 些用户提供信号而不给哪些用户提供信号. 写一个程序找出一个方案使得有线电视网在不亏本的情况 下使观看转播的用户尽可能多. 思路 树形

算法:poj 2749 &amp;amp; hdu 1815 Building roads(2-SAT + 二分,好题)

[题目大意] 有n个牛棚, 还有两个中转站S1和S2, S1和S2用一条路连接起来. 为了使得任意 牛棚两个都可以有道路联通,现在要让每个牛棚都连接一条路到S1或者S2. 有a对牛棚互相有仇恨, 所以不能让他们的路连接到同一个中转站.还有b对牛棚互相喜欢,所以他们的路必须连到同一个中专站. 道路的长度是两点的曼哈顿距离. 问最小的任意两牛棚间的距离中的最大值是多少? [思路] 两天前看了这题,当时没什么想法,今天又翻看了一下,想出来了. 每个 牛棚有可以选择S1或者S2,并且有矛盾对,是2-SA

算法题之poj 1961 Period(KMP, 最短循环节)

题目链接: POJ  : http://poj.org/problem?id=1961 HDU : http://acm.hdu.edu.cn/showproblem.php?pid=1358 ZOJ   : http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2177 题目大意: 给定一个长度为n的字符串s,求它的每个前缀的最短循环节.换句话说,对于每个i (2<=i<=n),求一个最大的整数K>1(如果K存在),使

算法题:poj 3080 Blue Jeans(KMP匹配,枚举子串)

链接: http://poj.org/problem?id=3080 题目大意: 给出m(2<=m<=10)个DNA序列, 求出这m个序列中最长的公共字串.如果有多个相同长度的, 输出字典序最小的. 分析与总结: 依次枚举所有的子串, 然后再看是否在所有序列中都能够匹配.保存下长度最大且字典序最小的序 列. 代码: #include<iostream> #include<cstdio> #include<cstring> using namespace st