您的位置:首页 > 其它

UVALive 3211 Now or later(2-sat)

2013-08-06 09:45 190 查看
2-sat问题,一种在两种可能性中选择必然关系的问题。

推荐两篇论文,也是学2-sat公认比较好的材料。前者较好理解,后者需耐心看。

http://www.google.com.hk/url?sa=t&rct=j&q=2-sat&source=web&cd=6&ved=0CEUQFjAF&url=http%3a%2f%2fbbs%2ebyr%2ecn%2fwForum%2fboardcon%2ephp%3fbid%3d212%26id%3d15887%26ftype%3d3%26ap%3d369&ei=30wAUsrlDYLHkwXam4GoBA&usg=AFQjCNHn7CqQ5EIiXNyfUmYM7jYYsIMfeQ&bvm=bv.50165853,d.dGI&cad=rjt

http://bbs.byr.cn/wForum/boardcon.php?bid=212&id=15890&ftype=3&ap=278

“最小值尽量大”问题,又是一种经典模型,二分答案,从而判断是否能构建出合适的方案。

代码看书码的,注意几点:

不能缩点,会把不成立的情况缩掉,所以改为标记。

一旦任意一点的两种可能性都不成立,即不存在完整的方案。

本题只是二选一,A或B的一种形式来建边的,其他形式的2-sat要通过做题去接触,不过,总的来说都是根据必然关系建图。

#include<stdio.h>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;

const int MAXN=2222;

int T[MAXN][2],n;
bool mark[MAXN<<1];
int S[MAXN<<1],c;
vector<int >G[MAXN<<1];

void init(int n)
{
for(int i=0;i<(n<<1);i++)
G[i].clear();
memset(mark,0,sizeof(mark));
}

void add(int x,int xval,int y,int yval)
{
x=(x<<1)+xval;
y=(y<<1)+yval;
G[x].push_back(y^1);
G[y].push_back(x^1);
}

bool dfs(int x)
{
if(mark[x^1])
return false;
if(mark[x])
return true;
S[c++]=x;
mark[x]=true;
for(int i=0;i<G[x].size();i++)
if(!dfs(G[x][i]))
return false;
return true;
}

bool solve()
{
for(int i=0;i<(n<<1);i+=2)
{
if(!mark[i]&&!mark[i+1]){
c=0;
if(!dfs(i)){
while(c>0)
mark[S[--c]]=false;
if(!dfs(i+1))
return false;
}
}
}
return true;
}

int test(int p)
{
init(n);
for(int i=0;i<n;i++)
for(int a=0;a<2;a++)
for(int j=i+1;j<n;j++)
for(int b=0;b<2;b++)
if(abs(T[i][a]-T[j][b])<p)
add(i,a,j,b);
return solve();
}

int main()
{
while(~scanf("%d",&n))
{
int l,r;
l=r=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<2;j++)
{
scanf("%d",&T[i][j]);
r=max(r,T[i][j]);
}
}
while(l<r)
{
int m=l+(r-l+1)/2;
if(test(m))
l=m;
else
r=m-1;
}
printf("%d\n",l);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: