Poj3683(2-set

poj3683

题目:有若干个活动可以选择两个时间段中的一个举行,询问使得所有活动不冲突的分配方案。

思路:2set裸题,sset需要先进行强联通分量分解,然后需要进行一次拓扑排序,但是如果强联通分量分解时使用两次dfs的方式,那么可以省去这一步。

/*
* @author:  Cwind
*/
///#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (3e-7)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF (1000000000)
#define FINF (1e3)
#define clr(x) memset((x),0,sizeof (x));
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,int> P;

const int maxn=2005;
int n;
int a[maxn][3];
char r[300];
vector<int> G[maxn],rG[maxn],od;
bool vis[maxn];
int sccid[maxn];
int get(char a,char b){
    return (a-‘0‘)*10+b-‘0‘;
}
bool inter(int a,int b,int c,int d){
    return !(a>=d||b<=c);
}
void addedge(int a,int b){
    G[a].pb(b);
    rG[b].pb(a);
}
void dfs1(int v){
    vis[v]=1;
    for(int i=0;i<G[v].size();i++){
        int u=G[v][i];
        if(!vis[u]) dfs1(u);
    }
    od.pb(v);
}
void dfs2(int v,int k){
    vis[v]=1;
    sccid[v]=k;
    for(int i=0;i<rG[v].size();i++){
        int u=rG[v][i];
        if(!vis[u]) dfs2(u,k);
    }
}
int V;
void scc(){
    clr(vis);od.clear();
    for(int i=1;i<=V;i++){
        if(!vis[i]) dfs1(i);
    }
    clr(vis);
    int id=1;
    for(int i=od.size()-1;i>=0;i--){
        int v=od[i];
        if(!vis[v]) dfs2(v,id++);
    }
}
void build(){
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(inter(a[i][0],a[i][0]+a[i][2],a[j][0],a[j][0]+a[j][2])){
                addedge(i,j+n);
                addedge(j,i+n);
            }
            if(inter(a[i][0],a[i][0]+a[i][2],a[j][1]-a[j][2],a[j][1])){
                addedge(i,j);
                addedge(j+n,i+n);
            }
            if(inter(a[i][1]-a[i][2],a[i][1],a[j][0],a[j][0]+a[j][2])){
                addedge(i+n,j+n);
                addedge(j,i);
            }
            if(inter(a[i][1]-a[i][2],a[i][1],a[j][1]-a[j][2],a[j][1])){
                addedge(i+n,j);
                addedge(j+n,i);
            }
        }
    }
}
bool ans[maxn];
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("defense.in","r",stdin);
    //freopen("defense.out","w",stdout);
    cin>>n;
    V=n*2;
    for(int i=1;i<=n;i++){
        scanf("%s",r);
        a[i][0]=get(r[0],r[1])*60+get(r[3],r[4]);
        scanf("%s",r);
        a[i][1]=get(r[0],r[1])*60+get(r[3],r[4]);
        scanf("%d",&a[i][2]);
    }
    build();
    scc();
    for(int i=1;i<=n;i++){
        if(sccid[i]==sccid[i+n]){
            puts("NO");
            return 0;
        }else{
            if(sccid[i]>sccid[i+n]){
                ans[i]=1;
            }else{
                ans[i]=0;
            }
        }
    }
    puts("YES");
    for(int i=1;i<=n;i++){
        if(ans[i]){
            int s=a[i][0],t=a[i][0]+a[i][2];
            printf("%02d:%02d %02d:%02d\n",s/60,s%60,t/60,t%60);
        }else{
            int s=a[i][1]-a[i][2],t=a[i][1];
            printf("%02d:%02d %02d:%02d\n",s/60,s%60,t/60,t%60);
        }
    }
    return 0;
}

时间: 2024-10-07 05:26:01

Poj3683(2-set的相关文章

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

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

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

【小结】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的点连一条有向边.因为