http://www.lydsy.com/JudgeOnline/problem.php?id=1997

1997: [Hnoi2010]Planar

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1810  Solved: 684
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5

Sample Output

NO
YES

思路:(from 出题人):http://www.cnblogs.com/jinkun113/p/4894499.html

如果只考虑简单的平面图判定,这个问题是非常不好做的。

但是题目中有一个条件——这张图存在一条哈密顿回路。

我们把哈密顿回路在平面上画成一个圆。仔细观察一下。

每条边如果画在圆内都是一条弦,那如果弦在圆内相交怎么办?把另一条弦翻出去。能不能两条弦都翻出去呢?不能,因为如果两条边在圆内相交,那么它们在圆外也会相交。那我们是不是就相当于就多了一个条件:这两条边不能同时在一个域内。
所以,这张图中总共只有两个域,圆内和圆外。那么我们是不是就转化了模型:有若干个点和若干条边,你要给每个点黑白染色,使得每条边的两个端点颜色不同。直接DFS就可以了。还有个问题,边数是10^4,暴力连边会超时,但是平面图有一个定理:m<=3*n+6,那这个定理来剪枝就行了。
 
 
然后我们只要对输入的哈密顿环进行标号,然后这样就是一个圈,假定刚开始都是在圈内,然后我们只需要判断是否在圈内就行了。

好像我的代码因为用了map和edges这些东西,所以跑的速度比别人慢一个log= =,别人都是200ms左右,我是2000ms,人生第一次体验到了map所带来的绝望

#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1e5 + ;
struct TwoSat{
int n, c, s[maxn * ];
bool mark[maxn << ];
vector<int> G[maxn << ]; void init(int n){
this->n = n;
for (int i = ; i < * n; i++) G[i].clear();
memset(mark, false, sizeof(mark));
} void add_edge(int x, int xval, int y, int yval){
x = x * + xval, y = y * + yval;
G[x ^ ].pb(y), G[y ^ ].pb(x);
} void display(){
for (int i = ; i < * n; i++){
printf("from = %d\n", i);
for (int j = ; j < G[i].size(); j++){
printf("%d ", G[i][j]);
}
cout << endl;
}
} bool dfs(int x){
if (mark[x ^ ]) return false;
if (mark[x]) return true;
mark[x] = true;
s[c++] = x;
for (int i = ; i < G[x].size(); i++){
if (!dfs(G[x][i])) return false;
}
return true;
} bool solve(){
for (int i = ; i < n * ; i += ){
if (!mark[i] && !mark[i + ]){
c = ;
if (!dfs(i)){
while (c) mark[s[--c]] = false;
if (!dfs(i + )) return false;
}
}
}
return true;
} };
TwoSat tar;
int n, m;
map<int, int> id;
map<pair<int, int>, int> Point;
vector<pair<int, int> > edges; bool test(int u1, int v1, int u2, int v2){
if (u2 > u1 && u2 < v1 && v2 > v1) return true;
if (u1 > u2 && u1 < v2 && v1 > v2) return true;
return false;
} int main(){
int T; cin >> T;
while (T--){
scanf("%d%d", &n, &m);
id.clear();
edges.clear();
for (int i = ; i < m; i++){
int u, v; scanf("%d%d", &u, &v);
if (u > v) swap(u, v);
edges.push_back(mk(u, v));
}
for (int i = ; i <= n; i++){
int u; scanf("%d", &u);
id[u] = i;
}
if (m >= n * + ){
puts("NO"); continue;
}
tar.init(m);
for (int i = ; i < m; i++){
int x1 = edges[i].fi, y1 = edges[i].se;
x1 = id[x1], y1 = id[y1];
if (x1 > y1) swap(x1, y1); for (int j = i + ; j < m; j++){
int x2 = edges[j].fi, y2 = edges[j].se;
x2 = id[x2], y2 = id[y2];
if (x2 > y2) swap(x2, y2);
//if (x1 == x2 || x1 == y2 || y1 == x2 || y1 == y2) continue;
if (test(x1, y1, x2, y2)){///假定刚开始都是在里面的
tar.add_edge(i, , j, );
tar.add_edge(i, , j, );
}
}
}
//tar.display();
if (tar.solve()) puts("YES");
else puts("NO");
}
return ;
}

条件转化,2-sat BZOJ 1997的更多相关文章

  1. HDU 3062 && HDU 1824 && POJ 3678 && BZOJ 1997 2-SAT

    一条边<u,v>表示u选那么v一定被选. #include <iostream> #include <cstring> #include <cstdio> ...

  2. [BZOJ 1997][HNOI2010]Planar(2-SAT)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1997 分析: 考虑每条边是在圈子里面还是圈子外面 所以就变成了2-SAT判定问题了= ...

  3. BZOJ 1997: [Hnoi2010]Planar( 2sat )

    平面图中E ≤ V*2-6.. 一个圈上2个点的边可以是在外或者内, 经典的2sat问题.. ----------------------------------------------------- ...

  4. bzoj 1997 [Hnoi2010]Planar——2-SAT+平面图的一个定理

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1997 平面图的一个定理:若边数大于(3*点数-6),则该图不是平面图. 然后就可以2-SAT ...

  5. Bzoj 1997 [Hnoi2010]Planar题解

    1997: [Hnoi2010]Planar Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2224  Solved: 824[Submit][Stat ...

  6. bzoj 1997: [Hnoi2010]Planar

    #include<cstdio> #include<cstring> #include<iostream> #define M 20005 #define N 20 ...

  7. 【BZOJ 1997】[Hnoi2010]Planar

    Description Input Output   找到哈密尔顿环之后找到不在哈密尔顿环上的边 这些边如果同时在里面相交那他们同时在外面也相交,所以只能一外一内,这就变成了2-SAT,判一下就好了 ...

  8. bzoj 1997: [Hnoi2010]Planar【瞎搞+黑白染色】

    脑补一下给出的图:一个环,然后有若干连接环点的边,我们就是要求这些边不重叠 考虑一下不重叠的情况,两个有交边一定要一个在环内一个在环外,所以把相交的边连边,然后跑黑白染色看是否能不矛盾即可(可能算个2 ...

  9. 装载:关于拉格朗日乘子法与KKT条件

    作者:@wzyer 拉格朗日乘子法无疑是最优化理论中最重要的一个方法.但是现在网上并没有很好的完整介绍整个方法的文章.我这里尝试详细介绍一下这方面的有关问题,插入自己的一些理解,希望能够对大家有帮助. ...

随机推荐

  1. "Hello World!"团队第四次会议

    Scrum立会 博客内容是: 1.会议时间 2.会议成员 3.会议地点 4.会议内容 5.todo list 6.会议照片 7.燃尽图 一.会议时间: 2017年10月16日  11:44-12:18 ...

  2. 欢迎来怼--第三十次Scrum会议

    一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/11/18 17:20~17:53,总计33min. 地 ...

  3. Spring的事务到底该给Dao配置还是给Service配置

    Spring的事务到底该给Dao配置还是给Service配置 Spring事务为业务逻辑进行事务管理,保证业务逻辑上数据的原子性. 事务得根据项目性质来细分:事务可以设置到三个层面(dao层.serv ...

  4. 博弈---威佐夫博奕(Wythoff Game)

    这个写的不错 威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同 时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜.     这种情况下是颇为复杂 ...

  5. 蜗牛慢慢爬 LeetCode 2. Add Two Numbers [Difficulty: Medium]

    题目 You are given two non-empty linked lists representing two non-negative integers. The digits are s ...

  6. 2nd scrum站立会议

    scrum站立会议 站立会议是让团队成员每日面对面站立互相交流他们所承担任务的进度.它的一个附带好处是让同组成员了解到工作的情况.本质上是为了团队交流,不是会议报告. 站立会议的目的: 1.让整个团队 ...

  7. PAT 甲级 1027 Colors in Mars

    https://pintia.cn/problem-sets/994805342720868352/problems/994805470349344768 People in Mars represe ...

  8. MySQL 分组排序问题

    SQL好久不写了,有些生疏了,一个分组排序问题想了快半天,整理下. 学生表 CREATE TABLE `t_student` ( `id` bigint(20) NOT NULL AUTO_INCRE ...

  9. 阿里巴巴分布式数据库服务DRDS研发历程

    淘宝TDDL研发历史和背景 分布式关系型数据库服务(Distribute Relational Database Service,简称DRDS)是一种水平拆分.可平滑扩缩容.读写分离的在线分布式数据库 ...

  10. 第153天:关于HTML标签嵌套的问题详解

    HTML标签 1.块级元素 div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.menu.noframe ...