POJ 2749--Building roads(2-SAT)

两天总算刷完了这六题,也算是有些收获吧。

先来说说建图的问题,之前我们可以看到都是建两条边,而这题得建四条边,为什么呢?

因为根据实际情况考虑吧他们前后都有可能。

所以在这里我们要得出结论,2-Sat题目就如同网络流,差分约束一样,根据题意给出的限制条件建图。

然后再说说这个tarjan,作用是用来缩点,把一堆点变成一个,然后我sb的写的top+1那种,以后要注意这种写法的问题。

对于输出一组解的题目呢,我们更要细心,时时刻刻心中默念自己i对应哪种状态,i+n对应哪种状态,然后1就是相同,0就是不同。

其实如何看出这是一道2-Sat题目呢,我们首先要确定他初始状态即为两个对立状态,如一个在内一个在外,一个在左一个在右,然后再去找他们的对立状态,确定& | ^的关系,然后建图即可。

By:大奕哥

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<vector>
  7 #include<queue>
  8 using namespace std;
  9 const int N=5005;
 10 int ecnt,n,m,nn,top,num,cnt,slen,mi,ma,ans,a,b;
 11 int head[N],low[N],dfn[N],col[N],vis[N],ss[N];
 12 struct point{
 13     int a,b;
 14 }s[3],p[N],away[N],gay[N];
 15 inline int len(point a,point b){return abs(a.a-b.a)+abs(a.b-b.b);}
 16 struct edge
 17 {
 18     int to,nex;
 19 }e[1000005];
 20 void add(int x,int y)
 21 {
 22     e[++ecnt].to=y;e[ecnt].nex=head[x];head[x]=ecnt;
 23 }
 24 void init()
 25 {
 26     ecnt=cnt=num=top=0;
 27     memset(head,0,sizeof(head));
 28     memset(low,0,sizeof(low));
 29     memset(dfn,0,sizeof(dfn));
 30     memset(vis,0,sizeof(vis));
 31     memset(col,0,sizeof(col));
 32 }
 33 void dfs(int x)
 34 {
 35     vis[x]=1;ss[++top]=x;
 36     low[x]=dfn[x]=++cnt;
 37     for(int i=head[x];i;i=e[i].nex)
 38     {
 39         int y=e[i].to;
 40         if(!dfn[y])
 41         {
 42             dfs(y);
 43             low[x]=min(low[x],low[y]);
 44         }
 45         else if(vis[y])
 46         {
 47             low[x]=min(low[x],dfn[y]);
 48         }
 49     }
 50     if(low[x]==dfn[x])
 51     {
 52         num++;
 53         while(ss[top]!=x)
 54         {
 55             int a=ss[top--];
 56             vis[a]=0;
 57             col[a]=num;
 58         }
 59         int a=ss[top--];
 60         vis[a]=0;
 61         col[a]=num;
 62     }
 63     return;
 64 }
 65 bool judge(int mid)
 66 {
 67     init();
 68     for(int i=0;i<a;++i)
 69     {
 70         add(away[i].a+n,away[i].b);//1&1=1 都选后面 
 71         add(away[i].b+n,away[i].a);    
 72         
 73         add(away[i].a,away[i].b+n);//1&1=1 都选前面 
 74         add(away[i].b,away[i].a+n);
 75     }
 76     for(int i=0;i<b;++i)
 77     {
 78         add(gay[i].a,gay[i].b);//1&0=0 一前一后 
 79         add(gay[i].b+n,gay[i].a+n);    
 80         
 81         add(gay[i].a+n,gay[i].b+n);//0&1=0 一后一前 
 82         add(gay[i].b,gay[i].a);
 83     }
 84     for(int i=1;i<=n;++i)
 85     {
 86         for(int j=i+1;j<=n;++j)
 87         {
 88             if((len(p[i],s[0])+len(p[j],s[0]))>mid)add(i,j+n),add(j,i+n);
 89             if((len(p[i],s[1])+len(p[j],s[1]))>mid)add(i+n,j),add(j+n,i);
 90             if((len(p[i],s[0])+slen+len(p[j],s[1]))>mid)add(i,j),add(j+n,i+n);
 91             if((len(p[i],s[1])+slen+len(p[j],s[0]))>mid)add(i+n,j+n),add(j,i);        
 92         }
 93     }
 94     for(int i=1;i<=n*2;++i)
 95     if(!dfn[i])dfs(i);
 96     for(int i=1;i<=n;++i)
 97     {
 98         if(col[i]==col[i+n])return 0;
 99     }
100     return 1;
101 }
102 
103 int main()
104 {
105 //    freopen("1.out","r",stdin);
106 //    freopen("my.out","w",stdout);
107     scanf("%d%d%d",&n,&a,&b);
108     scanf("%d%d%d%d",&s[0].a,&s[0].b,&s[1].a,&s[1].b);
109     slen=len(s[1],s[0]);mi=1e9,ma=0;
110     for(int i=1;i<=n;++i)
111     {
112         scanf("%d%d",&p[i].a,&p[i].b);
113         mi=min(mi,min(len(p[i],s[0]),len(p[i],s[1])));
114         ma=max(ma,max(len(p[i],s[0]),len(p[i],s[1])));
115     }
116     for(int i=0;i<a;++i)scanf("%d%d",&away[i].a,&away[i].b);
117     for(int i=0;i<b;++i)scanf("%d%d",&gay[i].a,&gay[i].b);
118     int l=mi*2,r=ma*2+slen,ans=-1;
119     while(l<=r)
120     {
121         int mid=l+r>>1;
122         if(judge(mid))r=mid-1,ans=mid;
123         else l=mid+1;
124     }
125     printf("%d
",ans);
126     return 0;
127 }
原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8312648.html