poj 3207 Panda's Trick(2-sat,建图)
来源:互联网 发布:宏正软件 编辑:程序博客网 时间:2024/05/21 01:47
题目:http://poj.org/problem?id=3207
题意:
一个圆上顺时针放着n个点,现在要连m条边,每条边可以从圆的内部连也可以从圆的外部连。
保证每个点最多连1条边,问是否能使所有的边都不相交。
分析:
典型的2-sat问题,主要考察建图。
建图:对于一条边i,在圆内记为i,在圆外记为i’。
设边i连接点A,B,边j连接点C,D。i与j在圆内是否相交就是线段AB与线段CD是否相交,用坐标判断一下。
可以证明,如果i与j在圆内不能共存,则在圆外也一定不能共存,即:
i在圆内,则j一定在圆外,建边i->j’
i在圆外,则j一定在圆内,建边i’->j
j在圆内,则i一定在圆外,建边j->i’
j在圆外,则i一定在圆内,建边j’->i
代码:
可以先求强连通分量,然后判断两个选择否在同一个块中?如果在同一块中,那么显然无解。
时间复杂度O(e)
#include <cstdio>#include <iostream>#include <vector>#include <algorithm>#include <cstring>#include <string>#include <map>#include <cmath>#include <queue>#include <set>#include <stack>using namespace std;const int N = 1000 + 10;vector<int> G[N];int pre[N], lowlink[N], sccno[N], dfs_clock, scc_cnt;stack<int> S;void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if(!sccno[v]) { lowlink[u] = min(lowlink[u], pre[v]); } } if(lowlink[u] == pre[u]) { ++scc_cnt; int x; do { x = S.top(); S.pop(); sccno[x] = scc_cnt; } while(x!=u); }}void find_scc(int n) { dfs_clock = scc_cnt = 0; memset(sccno, 0, sizeof(sccno)); memset(pre, 0, sizeof(pre)); for(int i = 0; i < n; i++) if(!pre[i]) dfs(i);}int a[N],b[N];int main() { int T, n, m; scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d",&a[i],&b[i]); if(a[i]>b[i])swap(a[i],b[i]); } for(int i=0; i<m; i++) for(int j=i+1; j<m; j++) if(a[i]<a[j]&&b[i]<b[j]&&b[i]>a[j]||a[i]>a[j]&&b[i]>b[j]&&a[i]<b[j]) { G[2*i].push_back(2*j+1); G[2*i+1].push_back(2*j); G[2*j].push_back(i*2+1); G[2*j+1].push_back(i*2); } find_scc(2*m); for(int i=0; i<2*m; i++) { if(sccno[i]==sccno[i^1]) { puts( "the evil panda is lying again" ); return 0; } } puts( "panda is telling the truth..." ); return 0;}
因为数据不大,套一下O(nm)模板居然更快==
///////// 题目相关#include<algorithm>TwoSAT solver; //模板可以参考上篇或者上上篇int a[N],b[N];int main() { int T, n, m; scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d",&a[i],&b[i]); if(a[i]>b[i])swap(a[i],b[i]); } solver.init(m); for(int i=0; i<m; i++) for(int j=i+1; j<m; j++) if(a[i]<a[j]&&b[i]<b[j]&&b[i]>a[j]||a[i]>a[j]&&b[i]>b[j]&&a[i]<b[j]) { solver.G[2*i].push_back(2*j+1); solver.G[2*i+1].push_back(2*j); solver.G[2*j].push_back(i*2+1); solver.G[2*j+1].push_back(i*2); } if(!solver.solve()) { puts( "the evil panda is lying again" ); } else puts( "panda is telling the truth..." ); return 0;}
0 0
- poj 3207 Panda's Trick(2-sat,建图)
- poj 3207 Ikki's Story IV - Panda's Trick 2-sat+建图
- poj 3207 Ikki's Story IV - Panda's Trick 2-sat+建图
- POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT判定)
- POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT判断)
- [poj 3207] Ikki\'s Story IV - Panda\'s Trick(2-sat or 并查集)
- POJ 3207 Ikki's Story IV - Panda's Trick(2-sat)
- POJ-3207-Ikki's Story IV - Panda's Trick(2-sat模板)
- POJ 3207 Ikki's Story IV - Panda's Trick(2-sat判解存在性)
- POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT)
- POJ 3207 Ikki's Story IV - Panda's Trick(2 - sat啊)
- poj--3207--Ikki's Story IV - Panda's Trick(2-sat)
- POJ 3207 Ikki's Story IV - Panda's Trick(2-sat)
- poj 3207 Ikki's Story IV - Panda's Trick (2-SAT)
- poj Ikki's Story IV - Panda's Trick (2-sat)
- POJ--3207[Ikki's Story IV - Panda's Trick] 第一道2—SAT
- POJ 3207 Ikki's Story IV - Panda's Trick 2-sat
- poj 3207 Ikki's Story IV - Panda's Trick#2-sat
- cmsplus实战之仿[我扫网]之二:仿站开发页面信息列表清单
- UVA 10970 Big Chocolate(水题)
- 第一篇
- cmsplus实战之仿[我扫网]之三:新建并配置仿站工程信息
- Codeforces Round #353 (Div. 2) D. Tree Construction (BST询问父亲节点)
- poj 3207 Panda's Trick(2-sat,建图)
- Build a Responsive UI with ConstraintLayout
- 杭电ACM1000题------java语言
- Linux学习之网络基础
- cmsplus实战之仿[我扫网]之四:安装整站下载器并下载仿站所有数据
- Linux文件与时间编程2
- UVa11997 K Smallest Sums 归并 + 优先队列
- 278. First Bad Version
- noip2012疫情控制