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(); }}
- poj 3683【2-SAT】
- poj 3683 2-sat
- poj 3683 2-sat
- poj 3683 2-sat
- POJ 3683 2-sat
- POJ 3683 2-sat
- poj 3683 2-sat
- POJ 3683 2-sat
- POJ-3683(2-SAT)
- poj 3683 2-SAT 拓扑排序输出
- POJ 3683 2-sat 输出解
- POJ 3683 2-SAT +输出方案
- 2-sat 问题 总结 例题poj 3683
- 2-SAT——POJ 3683
- poj 3683 2SAT入门+挑战模板
- POJ 3683 2-SAT 输出可行方案
- 2-sat POJ 3678
- POJ 3207 2-sat
- TableAdapter 的使用
- 顶点数组
- 为C程序员准备的0x10个最佳问题
- myeclipse 注册码
- HDU3938 并查集 并查集
- poj 3683【2-SAT】
- Openfire 好友状态的发送(用户登录)
- PAGE_ALIGN()
- 二 ARM工作模式
- 温故而知新——再读CMU巨著CSAPP
- 任天堂3DS降价40% 倒逼索尼PS Vita加快上市
- XML基础(二)
- GLU对象
- 查看mysql语句运行时间