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\n",ans); 126 return 0; 127 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。