首页 > 代码库 > two-sat hdu3062 UVALive 3211
two-sat hdu3062 UVALive 3211
2-sat就是给定形如 x=xval or y=yval的若干约数,求是否存在全部满足。
这是一种dfs的算法,参考大白书
hdu3062 基本上是模板题吧,xval和yval都告诉你了。
#include<bits/stdc++.h>using namespace std;const int N=(int)2e3+10;int n,m;int mark[N],s[N],top=0;vector<int> g[N];bool dfs(int x) { if(mark[x^1]) return 0;if(mark[x]) return 1; mark[x]=1;s[++top]=x; for(auto v:g[x]) if(!dfs(v)) return 0; return 1;}void add(int x,int xval,int y,int yval) { x=x*2+xval,y=y*2+yval; g[x^1].push_back(y),g[y^1].push_back(x);}bool solve() { for(int i=0;i<2*n;i+=2) if(!mark[i]&&!mark[i^1]){ top=0; if(!dfs(i)) { for(int j=top;j>=1;j--) mark[s[j]]=0;top=0; if(!dfs(i^1)) return 0; } } return 1;}void in() { for(int i=1;i<=m;i++) { int u,v,t1,t2; scanf("%d%d%d%d",&u,&v,&t1,&t2); add(u,t1,v,t2); } puts(solve()?"YES":"NO");}main() { while(~scanf("%d%d",&n,&m)){ for(int i=0;i<n*2;i++) g[i].clear(); memset(mark,0, sizeof(mark));memset(s,0,sizeof(s));in(); } return 0;}
UVALive 3211
我们可以考虑二分答案,判断这个答案满不满足我们可以用2-sat
如何建图?我们枚举所有的点,如果x (0/1)-y(0/1) < mid (0/1为是begin or and)那么就可以转换成 x=(0/1)^1 or y=(0/1)^1
对此跑一边2-sat就行了。
#include<bits/stdc++.h>using namespace std;const int N =(int)3e3+10;struct Two_Sat { int n; int top=0; int sta[N<<1]; vector<int> g[N<<1]; int mark[N<<1]; void init(int n) { this->n=n; for(int i=0;i<n*2;i++) g[i].clear(); memset(mark,0, sizeof(mark)); } void add(int x,int xval,int y,int yval) { x=x*2+xval,y=y*2+yval; g[x^1].push_back(y),g[y^1].push_back(x); } bool dfs(int x) { if(mark[x^1]) return 0;if(mark[x]) return 1; sta[++top]=x;mark[x]=1; for(auto v:g[x]) if(!dfs(v)) return 0; return 1; } bool solve() { for(int i=0;i<2*n;i+=2) if(!mark[i]&&!mark[i^1]) { top=0; if(!dfs(i)) { for(int j=top;j>=1;j--) mark[sta[j]]=0;top=0; if(!dfs(i^1)) return 0; } } return 1; }}WSM_AK;int Abs(int a){return a>0?a:-a;}int s[N][2],n;bool ok(int now) { WSM_AK.init(n); for(int i=1;i<=n;i++) for(int a=0;a<=1;a++) for(int j=i+1;j<=n;j++) for(int b=0;b<=1;b++) if(Abs(s[i][a]-s[j][b])<now) WSM_AK.add(i-1,a^1,j-1,b^1); return WSM_AK.solve();}main() { while(cin>>n&&n) { int l=0,r=0; for(int i=1;i<=n;i++) for(int k=0;k<=1;k++) scanf("%d",&s[i][k]),r=max(r,s[i][k]); while(l<r) { int mid=l+(r-l+1)/2; if(!ok(mid)) r=mid-1;//ans=mid; else l=mid; } printf("%d\n",l); } return 0;}
two-sat hdu3062 UVALive 3211
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。