poj 3683【2-SAT】

来源:互联网 发布:百度推广调价软件 编辑:程序博客网 时间:2024/05/01 23:14

题意是说,一个牧师要帮人举办婚礼庆典,给出每对新人的可用时间段s,e和举办庆典时长len,这个庆典只能在时间段前或时间段后举行并且这些时间段不能有冲突,问牧师能否为他们举办庆典,能就输出具体时间段。

解法:2-SAT

i表示甲婚礼前段,^i表示甲婚礼后段

j表示乙婚礼前段,^j表示乙婚礼后段

建图:

i与j有冲突,i-->^j,j-->^i

i与^j有冲突,i-->j,^j-->^i

^i与j有冲突,^i-->^j,j-->i

^i与^j有冲突,^i-->j,^j-->i

然后就按照赵爽同学写的那样强连通缩点,拓扑染色(具体看赵爽论文)。

#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <string.h>#include <deque>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <limits.h>using namespace std;int lowbit(int t){return t&(-t);}int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a>b?b:a;}#define LL long long#define PI acos(-1.0)#define N  1200*2#define INF INT_MAX#define eps 1e-8#define FRE freopen("a.txt","r",stdin)int low[N],dfn[N];int belong[N];bool inStack[N],vis[N];vector<int> v[N],g[N];stack<int> st;int n,m;int step,t;int conflict[N];//缩点后有矛盾的点int du[N];//入度int color[N];//1为红色,-1为蓝色,红色输出int top[N],cnt;struct node{    int s,e;    int len;}c[1200];void tarjan(int u){    int i;    step++;    st.push(u);    low[u]=dfn[u]=step;    vis[u]=1;    inStack[u]=1;    for(i=0;i<v[u].size();i++)    {        int x=v[u][i];        if(!vis[x])        {            tarjan(x);            low[u]=min(low[u],low[x]);        }        else        if(inStack[x])        low[u]=min(low[u],dfn[x]);    }    if(low[u]==dfn[u])    {        t++;        while(1)        {            int x=st.top();            st.pop();            belong[x]=t;            inStack[x]=0;            if(x==u)break;        }    }}void init(){    int i;    for(i=0;i<=2*n;i++)v[i].clear();}bool isConflict(int a,int b,int c,int d){    if(a>=d || b<=c)return false;    return true;}void Build(){    int i,j;    init();    for(i=1;i<=n-1;i++)    {        for(j=i+1;j<=n;j++)        {            if(isConflict(c[i].s, c[i].s+c[i].len, c[j].s, c[j].s+c[j].len))            {                v[i].push_back(j+n);                v[j].push_back(i+n);            }            if(isConflict(c[i].s, c[i].s+c[i].len, c[j].e-c[j].len, c[j].e))            {                v[i].push_back(j);                v[j+n].push_back(i+n);            }            if(isConflict(c[i].e-c[i].len, c[i].e, c[j].e-c[j].len, c[j].e))            {                v[i+n].push_back(j);                v[j+n].push_back(i);            }            if(isConflict(c[i].e-c[i].len, c[i].e, c[j].s, c[j].s+c[j].len))            {                v[i+n].push_back(j+n);                v[j].push_back(i);            }        }    }}void Rebuild()//逆图{    int i,j;    memset(du,0,sizeof(du));    for(i=1;i<=2*n;i++)    {        for(j=0;j<v[i].size();j++)        {            int a=belong[i],b=belong[v[i][j]];            if(a!=b)            {                g[b].push_back(a);                du[a]++;            }        }    }    for(i=1;i<=n;i++)    {        int a=belong[i],b=belong[i+n];        conflict[a]=b;//缩点后有矛盾的点        conflict[b]=a;    }}void topsort(){    int i,j;    queue<int> q;    for(i=1;i<=t;i++)    if(!du[i])q.push(i);    cnt=0;    while(!q.empty())    {        int x=q.front();        top[++cnt]=x;        q.pop();        for(i=0;i<g[x].size();i++)        {            int tmp=g[x][i];            du[tmp]--;            if(du[tmp]==0)            q.push(tmp);        }    }}void dfs_Blue(int u){    int i;    color[u]=-1;    for(i=0;i<g[u].size();i++)    {        int x=g[u][i];        if(!color[x])        dfs_Blue(x);    }}void dfs_Red(){    int i,j;    memset(color,0,sizeof(color));    for(i=1;i<=cnt;i++)    {        int x=top[i];        if(!color[x])        {            color[x]=1;//Red            dfs_Blue(conflict[x]);//把所有与x有矛盾的点及其子孙染蓝色        }    }}void output(){    int i,j;    printf("YES\n");    int t1,t2;    for(i=1;i<=n;i++)    {        int x=belong[i],y=belong[i+n];        if(color[x]==1)        {            t1=c[i].s;            t2=c[i].s+c[i].len;        }        if(color[y]==1)        {            t1=c[i].e-c[i].len;            t2=c[i].e;        }        printf("%02d:%02d %02d:%02d\n",t1/60,t1%60,t2/60,t2%60);    }}void solve(){    int i,j;    memset(vis,0,sizeof(vis));    memset(inStack,0,sizeof(inStack));    t=0,step=0;    for(i=1;i<=2*n;i++)    if(!vis[i])tarjan(i);    for(i=1;i<=n;i++)    if(belong[i]==belong[i+n])    {        printf("NO\n");        return ;    }    Rebuild();    topsort();    dfs_Red();    output();}int main(){    while(scanf("%d",&n)!=EOF)    {        int i,j;        for(i=1;i<=n;i++)        {            int h1,m1,h2,m2;            scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&c[i].len);            c[i].s=h1*60+m1;            c[i].e=h2*60+m2;        }        Build();        solve();    }}


原创粉丝点击