codeforces27D Ring Road 2
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:CF27D
正解:$2—SAT$
解题报告:
也是$2-SAT$裸题,判断线段相交之后,直接上$2-SAT$就好了。
但是判线段相交有一点难受啊,换了几种写法才搞对,最好是双向判断一下…'
注意输出方案的时候一般的做法就是将图反向之后拓扑排序,一路染色过去,我写的做法是直接根据强连通分量编号从小到大染色,每次染完之后就把另一个染为另一种颜色就好了。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> using namespace std; typedef long long LL; const int MAXN = 520; const int MAXM = 100011; int n,m; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } namespace SAT_2{ int ecnt,first[MAXN],to[MAXM],next[MAXM],dfn[MAXN],low[MAXN],bel[MAXN],top,stack[MAXN],scnt,col[MAXN]; bool pd[MAXN],hav[MAXN]; vector<int>w[MAXN]; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline void getlink(int x,int y){//连边需要连完整所有的推导关系! x<<=1; y<<=1; link(x,y|1); link(x|1,y); link(y,x|1); link(y|1,x); } inline void tarjan(int x){ dfn[x]=low[x]=++ecnt; pd[x]=1; stack[++top]=x; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(!dfn[v]) { tarjan(v); low[x]=min(low[x],low[v]); } else if(pd[v]) low[x]=min(low[x],low[v]); } if(dfn[x]==low[x]) { scnt++; while(stack[top]!=x) { pd[stack[top]]=0; w[scnt].push_back(stack[top]); bel[stack[top]]=scnt; top--; } pd[x]=0; bel[x]=scnt; w[scnt].push_back(x); top--; } } inline void work(){ ecnt=0; for(int i=2;i<=(m<<1)+1;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=m;i++) if(bel[i<<1]==bel[i<<1|1]) { puts("Impossible"); return ; } for(int i=1;i<=scnt;i++) { for(int j=0,ss=w[i].size();j<ss;j++) { int v=w[i][j]; hav[v]=hav[v^1]=true; for(int l=first[v];l;l=next[l]) { int vv=to[l]; //if(hav[vv]) continue; hav[vv]=hav[vv^1]=true; col[vv>>1]=(vv&1); } col[v>>1]=(v&1); } } for(int i=1;i<=m;i++) { if(col[i]) printf("o"); else printf("i"); } } } struct edge{ int x,y; }e[MAXN]; inline bool Cross(edge q,edge qq){ if(q.x<qq.x && qq.x<q.y && q.y<qq.y) return true; return false; } inline void work(){ using namespace SAT_2; n=getint(); m=getint(); for(int i=1;i<=m;i++) { e[i].x=getint(),e[i].y=getint(); if(e[i].x>e[i].y) swap(e[i].x,e[i].y); } for(int i=1;i<=m;i++) for(int j=1;j<=m;j++)//双向!!! if(Cross(e[i],e[j])) getlink(i,j); SAT_2::work(); } int main() { #ifndef ONLINE_JUDGE freopen("27.in","r",stdin); freopen("27.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!