码迷,mamicode.com
首页 > 其他好文 > 详细

HDU - 1815 Building roads (2-SAT)

时间:2015-08-11 12:15:21      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:给出N个农场,S1场地和S2场地的坐标,要求每个农场要么和S1场地连接要么和S2场地连接,且每个农场之间的连接距离的最大值最小
现在给出A种不可连接限制,表明两个农场不能和同一个场地连接
又给出B种连接限制,表明两个农场要和同一个场地连接

解题思路:这题处理时有点恶心
二分枚举最大距离L,判断一下每个农场可连接的场地(以下的连边表示,a表示和S1连接,!a表示和S2连接)
如果dist(a,S1) > L,那么a农场只能和S2连接了,连边a -> !a (a->!a表示只要dfs到a,那么必然返回false,说明a农场只能和S2相连)
如果dist(a,S2) > L,那么a农场只能和S1连接了,连边!a ->a

如果dist(a, S1) + dist(b,S1) > L,那么表明a和b不能同时和S1连接,连边a -> !b, b->!a
如果dist(a, S2) + dist(b,S2) > L,那么表明a和b不能同时和S2连接,连边!a -> b, !b->a
如果dist(a,S1) + dist(b, S2) + dist(S1,S2) > L,那么表明a农场连接S1时,b农场不能连接S2。b农场连接S2时,a农场不能连接S1,连边 a->b, !b->!a
如果dist(a,S2) + dist(b, S1) + dist(S1,S2) > L,那么表明a农场连接S2时,b农场不能连接S1。b农场连接S1时,a农场不能连接S2,连边 !a->!b, b->a

接下来还要处理A中不可连接限制和B种连接限制,这些就不提了,能处理上面的,下面的可定也能处理

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define N 1010
#define abs(a) ((a) > 0? (a): (-(a))) 

struct cows{
    int x, y;
}C[N], S1, S2, heat[N], like[N];

int n, m, a, b, top, dis_S1_S2;
int S[N], dis_S1[N], dis_S2[N];
bool mark[N];
vector<int> G[N];

void init() {
    scanf("%d%d%d%d", &S1.x, &S1.y, &S2.x, &S2.y);
    dis_S1_S2 = abs(S1.x - S2.x) + abs(S1.y - S2.y);

    for (int i = 0; i < m; i++) {
        scanf("%d%d", &C[i].x, &C[i].y);
        dis_S1[i] = abs(C[i].x - S1.x) + abs(C[i].y - S1.y);
        dis_S2[i] = abs(C[i].x - S2.x) + abs(C[i].y - S2.y);
    }

    for (int i = 0; i < a; i++) {
        scanf("%d%d", &heat[i].x, &heat[i].y);
        heat[i].x--; heat[i].y--;
    }

    for (int i = 0; i < b; i++) {
        scanf("%d%d", &like[i].x, &like[i].y); 
        like[i].x--; like[i].y--;
    }
}

bool dfs(int u) {
    if (mark[u ^ 1]) return false;
    if (mark[u]) return true;

    mark[u] = true;
    S[++top] = u;
    for (int i = 0; i < G[u].size(); i++)
        if (!dfs(G[u][i]))
            return false;
    return true;
}

void AddEdge(int x, int valx, int y, int valy) {
    x = 2 * x + valx;
    y = 2 * y + valy;
    G[x].push_back(y);
}

bool judge(int mid) {
    for (int i = 0; i < 2 * m; i++)
        G[i].clear();

    bool flag;
    for (int i = 0; i < m; i++) {
        flag = false;
        //不能和S1相连
        if (dis_S1[i] > mid) {
            AddEdge(i, 0, i, 1);
            flag = true;
        }
        //不能和S2相连
        if (dis_S2[i] > mid) {
            if (flag)
                return false;
            AddEdge(i, 1, i, 0);
        }
    }

    for (int i = 0; i < m; i++)
        for (int j = i + 1; j < m; j++) {
            //第i个和第j个能够和S1相连的情况
            if (dis_S1[i] <= mid && dis_S1[j] <= mid && dis_S1[i] + dis_S1[j] > mid) {
                    AddEdge(i, 0, j, 1);
                    AddEdge(j, 0, i, 1);
            }
            //第i个和第j个能够和S2相连的情况
            if (dis_S2[i] <= mid && dis_S2[j] <= mid && dis_S2[i] + dis_S2[j] > mid) {
                    AddEdge(i, 1, j, 0);
                    AddEdge(j, 1, i, 0);
            }

            //第i个和S1相连,第j个和S2相连
            if (dis_S1[i] <= mid && dis_S2[j] <= mid && dis_S1[i] + dis_S2[j] + dis_S1_S2 > mid) {
                    AddEdge(i, 0, j, 0);
                    AddEdge(j, 1, i, 1);
            }
            //第i个和S2相连,第j个和s1相连
            if (dis_S2[i] <= mid && dis_S1[j] <= mid && dis_S2[i] + dis_S1[j] + dis_S1_S2 > mid) {
                    AddEdge(i, 1, j, 1);
                    AddEdge(j, 0, i, 0);
            }
        }

    for (int i = 0; i < a; i++) {
        AddEdge(heat[i].x, 0, heat[i].y, 1);
        AddEdge(heat[i].x, 1, heat[i].y, 0);
        AddEdge(heat[i].y, 0, heat[i].x, 1);
        AddEdge(heat[i].y, 1, heat[i].x, 0);
    }

    for (int i = 0; i < b; i++) {
        AddEdge(like[i].x, 0, like[i].y, 0);
        AddEdge(like[i].x, 1, like[i].y, 1);
        AddEdge(like[i].y, 0, like[i].x, 0);
        AddEdge(like[i].y, 1, like[i].x, 1);
    }

    memset(mark, 0, sizeof(mark));

    for (int i = 0; i < 2 * m; i++) {
        if (!mark[i] && !mark[i ^ 1]) {
            top = 0;
            if (!dfs(i)) {
                while (top) mark[S[top--]] = false;
                if (!dfs(i ^ 1))
                    return false;
            }
        }
    }
    return true;
}

void solve() {
    int l = 0, r = 44444444, mid;
    int ans = -1;
    while (l <= r) {
        mid = (l + r) / 2;
        if (judge(mid)) {
            ans = mid; 
            r = mid - 1;
        }
        else 
            l = mid + 1;
    }
    printf("%d\n", ans);
}

int main() {
    while (scanf("%d%d%d", &m, &a, &b) != EOF) {
        init();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU - 1815 Building roads (2-SAT)

标签:

原文地址:http://blog.csdn.net/l123012013048/article/details/47417833

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!