您的位置:首页 > 产品设计 > UI/UE

poj2749 Building roads 2-sat

2015-08-25 16:28 363 查看
链接:http://poj.org/problem?id=2749

题意:有n个奶牛,每个奶牛有坐标。有两个集散地,给出坐标,每个奶牛要链接到其中一个集散地上,让最远的两个奶牛的距离(曼哈顿距离)最近。而且有的奶牛间互相讨厌,不能连在一个集散地上,有的互相喜欢,必须连在一个上。

思路:很明显的2-sat,不过还是跑偏了。。首先给出的限制关系还有集散地数量为2都符合2-sat,不过2-sat中没有距离,只是判定。不过只要二分最大值,判断是否可行就可以了。

//开始还以为要让距离和最小,完全读错题了,后来发现了= =

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof((a)))
#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define Ror(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define mp make_pair
#define pb push_back
#define inf 0x3f3f3f3f

void RI (int& x){
x = 0;
char c = getchar ();
while (c == ' '||c == '\n') c = getchar ();
bool flag = 1;
if (c == '-'){
flag = 0;
c = getchar ();
}
while (c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar ();
}
if (!flag) x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}

const int maxn = 1010;
int n,m;
struct Side{
int v,next;
}side[maxn*maxn];
int top,node[maxn];
int t,dfn[maxn],low[maxn],sum;
stack<int>s;
void add_side(int u,int v){
side[top] = (Side){v,node[u]};
node[u] = top++;
}
void init(){
memset(node,-1,sizeof(node));
memset(dfn,0,sizeof(dfn));
top=sum=t=0;
}
void dfs(int u){
dfn[u]=low[u]=++t;
s.push(u);
for(int i=node[u];i!=-1;i=side[i].next){
int v=side[i].v;
if(!dfn[v])dfs(v);
if(dfn[v]!=-1)low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u]){
int v;
do{
v=s.top();s.pop();
dfn[v]=-1;
low[v]=sum;
}while(v!=u);
sum++;
}
}
bool solve(){
for(int i=0;i<n;i++)//判断是否有可行解
if(low[2*i]==low[2*i+1])return false;
return true;
}

struct PP{
int x,y;
}pp[2],cow[maxn],hate[maxn],like[maxn];
int get_dis(PP a,PP b){
return abs(a.x - b.x) + abs(a.y - b.y);
}
int dis[maxn][2],ddd;
int a,b;

void build(int mid){
For(i,0,a){
int a = hate[i].x*2,b = hate[i].y*2;
int fa = a+1,fb = b+1;
add_side(a,fb);
add_side(fa,b);
add_side(b,fa);
add_side(fb,a);
}
For(i,0,b){
int a = like[i].x*2,b = like[i].y*2;
int fa = a+1,fb = b+1;
add_side(a,b);
add_side(fa,fb);
add_side(b,a);
add_side(fb,fa);
}
For(i,0,n){
For(j,i+1,n){
For(a,0,2){
For(b,0,2){
if(a == b){
if(dis[i][a] + dis[j][b] > mid){
add_side(i*2+a,j*2+(!b));
add_side(j*2+b,i*2+(!a));
}
}
else {
if(dis[i][a] + dis[j][b] + ddd > mid){
add_side(i*2+a,j*2+(!b));
add_side(j*2+b,i*2+(!a));
}
}
}
}
}
}
}
int get_ans(){
int l = 0,r = 6000010,mid;
while(l < r){
init();
mid = (l + r)>>1;
build(mid);
For(i,0,2*n)
if(!dfn[i])dfs(i);
if(solve())r = mid;
else l = mid + 1;
}
if(r == 6000010)return -1;
return r;
}
int main()
{
//freopen("test.txt","r",stdin);
while(~scanf("%d%d%d",&n,&a,&b)){
RII(pp[0].x,pp[0].y);
RII(pp[1].x,pp[1].y);
ddd = get_dis(pp[0],pp[1]);
For(i,0,n){
RII(cow[i].x,cow[i].y);
}
For(i,0,n){
For(j,0,2){
dis[i][j] = get_dis(pp[j],cow[i]);
}
}
For(i,0,a){
RII(hate[i].x,hate[i].y);
hate[i].x --;
hate[i].y --;
}
For(i,0,b){
RII(like[i].x,like[i].y);
like[i].x --;
like[i].y --;
}
int ans = get_ans();
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2-sat