HDU 4115 Eliminate the Conflict【2011 ACM Asia Chengdu Regional Problem E】
2011-11-09 10:55
225 查看
赛前告诉小朋友们去年区域赛出了两题2-sat,今年不会出了,然后我就错了。而且集训队的2-sat是我讲的,结果导致他们三个队都没过,何等罪过啊 T_T
题目意思很简单,两个人石头剪刀布,一个人的出法是确定的,另一个人的出法有一定约束,某两次要相同或者不同,问你第二个人能否全部都不失败。题目还是很容易想到2-sat的,不过按照官方题解里说的每次出拳拆分成两个相对点的建图方法相当麻烦,小明哥按照那种方法建图就写了5k那么长,比较容易理解的方法是拆六个点:
石头(R), 非石头(~R)
布(P), 非布(~P)
剪刀(S), 非剪刀(~S)
每次只能三者取一个,那么就是如果出了一个,另外两个就不能出
R->~P, R->~S, P->~R, P->~S, S->~R, S->~P
然后根据对方的出法,就只能出平局和胜局两种出法
比如:如果对方是石头(R),那么只能出R和P,非R即P,非P即R
~R->P, ~P->R
最后就是加入约束关系,如果两次必须相同:
R1<->R2, P1<->P2, S1<->S2 均是双向边
如果不同也是一样
R1->~R2, R2->~R1, ......
这样建好图之后跑一边2-sat模板就能A掉了
比赛时候模板敲错,查了三个多小时,还好最后A掉,不然就去卧轨了 T_T
两个点的建图方法也很容易理解,每一次只有两种出法,平局或是胜局,即如果对方是S,那么只能是R或者P,R和P是两个相对点,这样就省去了上面方法中的前两种建图。不过这时要记下对应的两个点是什么,然后建图就要讨论很多很多东西了:
比如说如果两次分别是RP1和SP2,两次必须相同时候建图
第一次有P,第二次也有P,那么第一个P和第二个P变为强连通,P1<->P2
第一次有R,第二次没R,那么就是R->P1,表示这种情况不可能
S同样,S->P2建边,不可能存在的情况
各种情况讨论下去,然后做强连通
这样做时间和内存都会少很多,但是代码量大了很多,对于O(n+m)的这种算法作用不大...
题目意思很简单,两个人石头剪刀布,一个人的出法是确定的,另一个人的出法有一定约束,某两次要相同或者不同,问你第二个人能否全部都不失败。题目还是很容易想到2-sat的,不过按照官方题解里说的每次出拳拆分成两个相对点的建图方法相当麻烦,小明哥按照那种方法建图就写了5k那么长,比较容易理解的方法是拆六个点:
石头(R), 非石头(~R)
布(P), 非布(~P)
剪刀(S), 非剪刀(~S)
每次只能三者取一个,那么就是如果出了一个,另外两个就不能出
R->~P, R->~S, P->~R, P->~S, S->~R, S->~P
然后根据对方的出法,就只能出平局和胜局两种出法
比如:如果对方是石头(R),那么只能出R和P,非R即P,非P即R
~R->P, ~P->R
最后就是加入约束关系,如果两次必须相同:
R1<->R2, P1<->P2, S1<->S2 均是双向边
如果不同也是一样
R1->~R2, R2->~R1, ......
这样建好图之后跑一边2-sat模板就能A掉了
比赛时候模板敲错,查了三个多小时,还好最后A掉,不然就去卧轨了 T_T
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 60005 #define M 999999 struct Edge{ int vtx,next; }E[M]; int head ,size; int dfn ,low ,blg ,step,scc; int stk ,top; bool ins ; void Init(){ memset(head,-1,sizeof(head)); memset(dfn,-1,sizeof(dfn)); memset(ins,false,sizeof(ins)); step=size=0; top=-1; } void Insert(int u,int v){ E[size].vtx=v; E[size].next=head[u]; head[u]=size++; } void Tarjan(int u){ stk[++top]=u; ins[u]=true; dfn[u]=low[u]=step++; for(int i=head[u];~i;i=E[i].next){ int v=E[i].vtx; if(dfn[v]==-1){ Tarjan(v); low[u]=min(low[u],low[v]); }else if(ins[v]){ low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]){ for(int v=-1;v!=u;top--){ v=stk[top]; ins[v]=false; blg[v]=scc; } scc++; } } int main(){ int t,cas=0; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); Init(); for(int i=0;i<n;i++){ Insert(i*6+0,i*6+3); Insert(i*6+0,i*6+5); Insert(i*6+2,i*6+1); Insert(i*6+2,i*6+5); Insert(i*6+4,i*6+1); Insert(i*6+4,i*6+3); } for(int i=0;i<n;i++){ int v; scanf("%d",&v); if(v==1){ Insert(i*6+3,i*6+0); Insert(i*6+1,i*6+2); }else if(v==2){ Insert(i*6+5,i*6+2); Insert(i*6+3,i*6+4); }else if(v==3){ Insert(i*6+5,i*6+0); Insert(i*6+1,i*6+4); } } for(int i=0;i<m;i++){ int a,b,v; scanf("%d%d%d",&a,&b,&v); a--; b--; if(v){ Insert(a*6+0,b*6+1); Insert(a*6+2,b*6+3); Insert(a*6+4,b*6+5); Insert(b*6+0,a*6+1); Insert(b*6+2,a*6+3); Insert(b*6+4,a*6+5); }else{ Insert(a*6+0,b*6+0); Insert(a*6+2,b*6+2); Insert(a*6+4,b*6+4); Insert(b*6+0,a*6+0); Insert(b*6+2,a*6+2); Insert(b*6+4,a*6+4); } } for(int i=0;i<n*6;i++){ if(dfn[i]==-1) Tarjan(i); } bool flag=true; for(int i=0;i<n*3;i++){ if(blg[i<<1]==blg[i<<1|1]){ flag=false; break; } } printf("Case #%d: ",++cas); puts(flag?"yes":"no"); } }
两个点的建图方法也很容易理解,每一次只有两种出法,平局或是胜局,即如果对方是S,那么只能是R或者P,R和P是两个相对点,这样就省去了上面方法中的前两种建图。不过这时要记下对应的两个点是什么,然后建图就要讨论很多很多东西了:
比如说如果两次分别是RP1和SP2,两次必须相同时候建图
第一次有P,第二次也有P,那么第一个P和第二个P变为强连通,P1<->P2
第一次有R,第二次没R,那么就是R->P1,表示这种情况不可能
S同样,S->P2建边,不可能存在的情况
各种情况讨论下去,然后做强连通
这样做时间和内存都会少很多,但是代码量大了很多,对于O(n+m)的这种算法作用不大...
相关文章推荐
- HDU 4115 Eliminate the Conflict(2-SAT)(2011 Asia ChengDu Regional Contest)
- hdu 4091 Zombie’s Treasure Chest【2011 ACM Asia Shanghai Regional Problem A】
- The 36th ACM/ICPC Asia Regional Beijing Site&&http://acm.hdu.edu.cn/showproblem.php?pid=4046
- HDU 4729 An Easy Problem for Elfness(主席树)(2013 ACM/ICPC Asia Regional Chengdu Online)
- HDU 4127 Flood-it!【2011 ACM Asia Fuzhou Regional Problem G】
- hdu 5443 The Water Problem 2015 ACM/ICPC Asia Regional Changchun Online
- HDU 4033 4036 4039 The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest
- HDU 4031 Attack(离线+线段树)(The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest)
- HDU 5443 The Water Problem(水题 找区间最大值)——2015 ACM/ICPC Asia Regional Changchun Online
- HDU 5443 The Water Problem 2015 ACM/ICPC Asia Regional Changchun Online
- hdu 4055 Number String【2011 ACM Asia Dalian Regional Problem E】
- Hdu 4057 Rescue the Rabbit (AC自动机+状态压缩dp) - 2011 ACM-ICPC Dalian Regional Contest Problem G
- 2014-2015 ACM-ICPC, Asia Xian Regional Contest GThe Problem to Slow Down You
- The 2012 ACM-ICPC Asia Changchun Regional Contest(problem E)
- 回文自动机 + DFS --- The 2014 ACM-ICPC Asia Xi’an Regional Contest Problem G.The Problem to Slow Down You
- hdu 4727 The Number Off of FFF 简单题( 2013 ACM/ICPC Asia Regional Online —— Warmup2 1012)
- zoj 3418 || The 2010 ACM-ICPC Asia Chengdu Regional Contest - C Binary Number
- hdu 4737 A Bit Fun 数列(2013 ACM/ICPC Asia Regional Chengdu Online 1010)
- HDU-4027 Can you answer these queries? (线段树 区间修改 区间查询)(The 36th ACM/ICPC Asia Regional Shanghai)
- HDU 4115 Eliminate the Conflict(2-sat 判解存在性)