poj3683

题解:

2-sat

然后不用拓扑

直接强连通的逆序就可以了

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2005;
int flag[N],ans,l,n;
int ne[N*N],fi[N],a[N],b[N],zz[N*N],num,t,zhan[N],dfn[N],low[N],an[N];
void jb(int x,int y)
{
    ne[++num]=fi[x];
    fi[x]=num;
    zz[num]=y;
}
void dfs(int x)
{
    low[x]=dfn[x]=++l;
    zhan[++t]=x;
    flag[x]=true;
    for (int i=fi[x];i!=0;i=ne[i])
     {
         if (an[zz[i]])continue;
        if(!dfn[zz[i]])dfs(zz[i]);
        if(!flag[zz[i]])low[x]=min(low[x],dfn[zz[i]]);else
        low[x]=min(low[x],low[zz[i]]);
     }
    if (dfn[x]==low[x])
     {
         ans++;
         while (zhan[t]!=x)
          {
              flag[zhan[t]]=false;
              an[zhan[t--]]=ans;
          }
         an[zhan[t--]]=ans;
         flag[x]=false;
     }
}
int read()
{
    int x=0;char c;
    for (;c<‘0‘||c>‘9‘;c=getchar());
    for (;c>=‘0‘&&c<=‘9‘;c=getchar())x=x*10+c-48;
    return x;
}
int pd(int x,int y)
{
    if (a[x]>a[y])swap(x,y);
    return b[x]>a[y];
}
void sget(int x)
{
    if (x<10)printf("0");
    printf("%d",x);
}
int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)
     {
         a[i]=read()*60+read();
         b[i+n]=read()*60+read();
         b[i]=read();a[i+n]=b[i+n]-b[i];
         b[i]+=a[i];
     }
    for (int i=0;i<2*n;i++)
     for (int j=i+1;j<2*n;j++)
      if (i%n!=j%n&&pd(i,j))
       jb(i,(j+n)%(2*n)),jb(j,(i+n)%(2*n));
    for (int i=0;i<2*n;i++)
     if (!dfn[i])dfs(i);
    for (int i=0;i<n;i++)
     if (an[i]==an[i+n])
      {
          puts("NO");
          return 0;
      }
    puts("YES");
    for (int i=0;i<n;i++)
     if (an[i]<an[i+n])
      {
          sget(a[i]/60);printf(":");
          sget(a[i]%60);printf(" ");
          sget(b[i]/60);printf(":");
          sget(b[i]%60);
          puts("");
      }
     else
      {
          sget(a[i+n]/60);printf(":");
          sget(a[i+n]%60);printf(" ");
          sget(b[i+n]/60);printf(":");
          sget(b[i+n]%60);
          puts("");
      }
    return 0;
}
时间: 2024-11-09 00:07:40

poj3683的相关文章

POJ-3683 Priest John&#39;s Busiest Day

图论中的2-SAT.模板题. #include <cstdio> #include <cstdlib> #include <algorithm> #include <cctype> #include <cstring> #include <iostream> using namespace std; #define rep(i, l, r) for(int i=l; i<=r; i++) #define travel(x) fo

Poj3683(2-set

poj3683 题目:有若干个活动可以选择两个时间段中的一个举行,询问使得所有活动不冲突的分配方案. 思路:2set裸题,sset需要先进行强联通分量分解,然后需要进行一次拓扑排序,但是如果强联通分量分解时使用两次dfs的方式,那么可以省去这一步. /* * @author: Cwind */ ///#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <m

2-sat问题,输出方案,几种方法(赵爽的论文染色解法+其完全改进版)浅析 / POJ3683

本文原创于  2014-02-12 09:26. 今复习之用,有新体会,故重新编辑. 2014-02-12 09:26: 2-sat之第二斩!昨天看了半天论文(赵爽的和俉昱的),终于看明白了!好激动有木有!终于理解了赵爽的每一句话!并且用了200+行代码实现,A了!具体过程我是敲了帮天的代码啊!!!不容易啊!步骤如下: 把相关问题编号为01 23 45....,(每个编号为一个命题)奇数为取,偶数不取,那么相邻俩个互逆,于是根据具体情况(check)一下,建立图,tarjan判断有无解,然后顺便

poj3683 Priest John&#39;s Busiest Day

不用topsort的,我也不知道为啥. #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Node{ int fro, too; }nd[2005]; struct Edge{ int too, nxt, val; }edge[4000005]; int uu, vv, ww, n, hea[2005], cnt, dfn[2005], loo[200

Poj3683:Priest John&#39;s Busiest Day

题意 n对夫妻要结婚,第i对夫妻结婚的婚礼持续时间为[Si, Ti],他们会举行一个仪式,仪式时间为Di,这个仪式只能举行在开头或者结尾举行,要么[Si, Si+Di],要么[Ti-Di, Ti],然而举行仪式的牧师只有一个,问牧师能否举行完所有仪式 按输入顺序输出方案 手动翻译 Sol \(2-SAT\)输出一组可行解 这个很烦 \(Tarjan\)缩点成\(DAG\)后再拓扑排序+染色 只传递不选的标记 # include <iostream> # include <stdio.h&

poj3683 2-SAT 同上一道

Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10151   Accepted: 3475   Special Judge Description John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old l

POJ3683 Falsita

http://poj.org/problem?id=3683 思路:2-SAT,输出任意一组方案,O(m+n) 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 int first[2000005],next[2000005],tot,go[2000005]; 7 int First[20000

【小结】2-sat

2?sat 小结 2?sat解决的是可满足性问题,并且每个合取范式中的文字个数不多于2个. 形式为: (a∨?b)∧(?c∨?d)∧(?a∨d)? 将所有a∨b改成(?a?b)∧(?b?a) 建边,每个变量a对应两个点a和a+n 如果存在cmp[a]==cmp[a+n]不成立,否则成立.且如果cmp[a]>cmp[a+n],令a=true,否则令a=false即为原式的一组解. #include <cstdio> #include <iostream> #include &l

浅谈2-sat的问题的构造与求解

2-sat问题是一种常见的问题.给定若干个01变量,变量之间满足一些二元约束,求是否有解存在.若存在,给出可行解或按照字典序给出最优解. 下面给出与其对应的图论模型:给每个变量i设立2个点,我的习惯是记为T(i),F(i),分别表示其值取1,0. 下面考虑的便是如何进行限制了. 一般的限制形式均如下所示: 变量i取x时,变量j只能取y,那么表示i取x的点向表示j取y的点连一条有向边.表示推出关系. 类似的,若表示变量i取x时,变量j不能取y,那么表示i取x的点向表示j取~y的点连一条有向边.因为