POJ 2749--Building roads(2-SAT)
题意:John有n个牛棚,每个牛棚都住着一些牛,这些牛喜欢串门(drop around, 学到了。。。),所以John想要建几条路把他们连接起来。他选择的方法是建两个相连中转站,然后每个牛棚连接其中一个中转站就好啦。现在的问题是有一些牛相互憎恨,所以不能连同一个中转站,而又有一些牛相互喜欢,必须连同一个中转站(再次感叹,人不如牛。。),现在要你来建边,要求,任意两个牛棚的距离的最大距离最短。两点距离是指哈密顿距离。比如u, v连的是同一个中转站s1,距离就是dis(u,s1)+dis(v,s1) 如果连不同的中转站就是dis(u,s1)+dis(v,s2)+dis(u,v),题意真的好不清楚啊
输入就是每个牛棚的坐标的中转站的坐标,已经牛之间的憎恨和喜欢关系。
输出最小距离。不能输出-1。
题解:二分。。。然后符合要求的边建图,2-sat求解。建图时喜欢和讨厌都要建四条边,仔细读题。。。仔细建边。。。
//我真的想吐槽我以前用的输入挂啊,我特么从哪搞来的辣鸡读入。。。用一次错一次。。。。
这套题做的我心真累。。。没有特别难的。。。但是每一道都wa的想死。。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <bitset>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define pk(x) printf("%d\n", x)
using namespace std;
#define PI acos(-1.0)
#define EPS 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
typedef long long ll;
const int N = ;
const int M = ;
inline int Scan()
{
char ch = getchar();
int data = ;
while (ch < '' || ch > '') ch = getchar();
do {
data = data* + ch-'';
ch = getchar();
} while (ch >= '' && ch <= '');
return data;
}
struct Edge {
int from, to, next;
} edge[M];
int head[N];
int cntE;
void addedge(int u, int v) {
edge[cntE].from = u; edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
} int dfn[N], low[N], idx;
int stk[N], top;
int in[N];
int kind[N], cnt; void tarjan(int u)
{
dfn[u] = low[u] = ++idx;
in[u] = true;
stk[++top] = u;
for (int i = head[u]; i != -; i = edge[i].next) {
int v = edge[i].to;
if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if (in[v]) low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
++cnt;
while () {
int v = stk[top--]; kind[v] = cnt; in[v] = false;
if (v == u) break;
}
}
} void init() {
cntE = ;
memset(head, -, sizeof head);
memset(dfn, , sizeof dfn);
memset(in, false, sizeof in);
idx = top = cnt = ;
} int ax[N], ay[N];
int bx[N], by[N];
int dis1[N], dis2[N];
int n, a, b;
int dis; int cal(int x1, int y1, int x2, int y2) {
return abs(x1-x2) + abs(y1-y2);
} bool ok(int x) {
init();
for (int i = ; i <= n; ++i) {
for (int j = i+; j <= n; ++j) {
if (dis1[i] + dis1[j] > x) addedge(i, n+j), addedge(j, n+i);
if (dis2[i] + dis2[j] > x) addedge(i+n, j), addedge(j+n, i);
if (dis1[i] + dis2[j] + dis > x) addedge(i, j), addedge(j+n, i+n);
if (dis2[i] + dis1[j] + dis > x) addedge(i+n, j+n), addedge(j, i);
}
}
for (int i = ; i < a; ++i) {
addedge(ax[i], ay[i] + n), addedge(ay[i] + n, ax[i]);
addedge(ay[i], ax[i] + n), addedge(ax[i] + n, ay[i]);
}
for (int i = ; i < b; ++i) {
addedge(bx[i], by[i]), addedge(by[i], bx[i]);
addedge(bx[i] + n, by[i] + n), addedge(by[i] + n, bx[i] + n);
} for (int i = ; i <= *n; ++i) if (!dfn[i]) tarjan(i); for (int i = ; i <= n; i++) if (kind[i] == kind[i + n]) return false;
return true;
} int main() {
int x1, y1, x2, y2;
int x, y;
while (~scanf("%d%d%d", &n, &a, &b)) {
x1 = Scan(); y1 = Scan(); x2 = Scan(); y2 = Scan();
dis = cal(x1, y1, x2, y2);
int maxn = ;
for (int i = ; i <= n; ++i) {
x = Scan(); y = Scan();
dis1[i] = cal(x, y, x1, y1);
dis2[i] = cal(x, y, x2, y2);
maxn = max(maxn, max(dis1[i], dis2[i]));
}
maxn = maxn * + dis;
for (int i = ; i < a; ++i) ax[i] = Scan(), ay[i] = Scan();
for (int i = ; i < b; ++i) bx[i] = Scan(), by[i] = Scan(); int l = , r = maxn;
int ans = -;
while (l <= r) {
int mid = (l+r) >> ;
if (ok(mid)) ans = mid, r = mid - ;
else l = mid + ;
}
printf("%d\n", ans);
}
return ;
}
POJ 2749--Building roads(2-SAT)的更多相关文章
- HDU 1815, POJ 2749 Building roads(2-sat)
HDU 1815, POJ 2749 Building roads pid=1815" target="_blank" style="">题目链 ...
- poj 2749 Building roads (二分+拆点+2-sat)
Building roads Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6229 Accepted: 2093 De ...
- poj 3625 Building Roads(最小生成树,二维坐标,基础)
题目 //最小生成树,只是变成二维的了 #define _CRT_SECURE_NO_WARNINGS #include<stdlib.h> #include<stdio.h> ...
- POJ 3678 Katu Puzzle(2 - SAT) - from lanshui_Yang
Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a ...
- POJ 1947 Rebuilding Roads (树形DP)
题意:给一棵树,在树中删除一些边,使得有一个连通块刚好为p个节点,问最少需要删除多少条边? 思路: 因为任一条边都可能需要被删除,独立出来的具有p个节点的连通块可能在任意一处地方.先从根开始DFS,然 ...
- HDU1815 Building roads(二分+2-SAT)
Problem Description Farmer John's farm has N barns, and there are some cows that live in each barn. ...
- POJ 1947 Rebuilding Roads(树形DP)
题目链接 题意 : 给你一棵树,问你至少断掉几条边能够得到有p个点的子树. 思路 : dp[i][j]代表的是以i为根的子树有j个节点.dp[u][i] = dp[u][j]+dp[son][i-j] ...
- [poj] 2749 building roads
原题 2-SAT+二分答案! 最小的最大值,这肯定是二分答案.而我们要2-SATcheck是否在该情况下有可行解. 对于目前的答案limit,首先把爱和恨连边,然后我们n^2枚举每两个点通过判断距离来 ...
- POJ 2749 Building roads 2-sat+二分答案
把爱恨和最大距离视为限制条件,可以知道,最大距离和限制条件多少具有单调性 所以可以二分最大距离,加边+check #include<cstdio> #include<algorith ...
- Java实现 POJ 2749 分解因数(计蒜客)
POJ 2749 分解因数(计蒜客) Description 给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * - * an,并且1 < a1 <= ...
随机推荐
- 【网络】IP地址分配、端口号、分层
3.网络分层 OSI的七层网络结构图和TCP/IP的五层结构图 OSI七层模型OSI中的层 功能 ...
- HDU4704+费马小定理
费马小定理题意:求s1+s2+s3+...+sn;si表示n划分i个数的n的划分的个数,如n=4,则s1=1,s2=3 利用隔板定理可知,就是求(2^n-1)%mod-----Y 现在已知 ...
- 【无聊放个模板系列】BZOJ 1597 斜率优化
STL 双向队列DEQUE版本 #include<cstdio> #include<cstdlib> #include<cstring> #include<i ...
- thinkphp 分组
分组 配置项: // 开启分组 'APP_GROUP_LIST'=>'Home,Admin', // 默认分组 'DEFAULT_GROUP'=>'Home', 涉及分组: 配置文件分组, ...
- nginx比较apache
http://blog.csdn.net/hanghangaidoudou/article/details/8506963 话说nginx在大压力的环境中比apache的表现要好,于是下载了一个来折腾 ...
- Linux防火墙iptables简明教程
前几天微魔部落再次遭受到个别别有用心的攻击者的攻击,顺便给自己充个电,复习了一下linux下常见的防火墙iptables的一些内容,但是无奈网上的很多教程都较为繁琐,本着简明化学习的目的,微魔为大家剔 ...
- 借助CAD在Altium Designer中定义不规则PCB外形
借助绘图软件CAD在Altium Designer中定义不规则PCB外形. 工具/原料 CAD2007 Altium Designer2015 方法/步骤 借助CAD绘制的不规则外形,保存成DXF格式 ...
- 第二个C语言代码
有问题,还没找出哪里出错了 输入一串字符,问号结束 统计1~9各出现的次数 ******************************************************** ...
- 理解TCP/IP协议
TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议. 单从TCP/IP协议这个名称看,好多人误 ...
- fork、vfork、clone区别
在Linux中主要提供了fork.vfork.clone三个进程创建方法. 问题 在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到s ...