POJ 3207 2-sat 判断是否有合法解
来源:互联网 发布:ipad无法下载软件 编辑:程序博客网 时间:2024/05/22 15:47
---------------------------------------------------------------------------------------------------------以下转载自http://cainiao2hao.blogcn.com/articles/poj3207.html
平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。
解题报告:题意可能刚开始不是很好理解,比如1 5连边,2,6连边,由于点是顺序排列的,一画图就可以发现,这两条边必须一个从圆外面连,一个从内部连,否则就会相交。如果再加入3 7这条边,那么就必须相交了。
这样,就可以转化成标准的2-sta问题:
1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i'
2:如果两条边i和j必须一个画在内部,一个画在外部(一个简单判断就可以)
那么连边:
i->j’, 表示i画内部的话,j只能画外部,即j’
j->i’,同理
i’->j,同理
j’->i,同理
然后就是2-sat算法了,tarjan一下,如果有i和i'同属于一个强联通,返回false,否则就成立。
------------------------------------------------------------------------------------------------------------------------
然后是我的代码
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#define MAXN 1005#define MAXM 2000005#define INF 1000000000using namespace std;int n, m, e, head[MAXN];int dfn[MAXN], low[MAXN], index, instack[MAXN], scc;int top, st[MAXN], fa[MAXN];int x[MAXN], y[MAXN];struct Edge{ int v, next;}edge[MAXM];void init(){ e = index = scc = top = 0; memset(dfn, 0, sizeof(dfn)); memset(instack, 0, sizeof(instack)); memset(head, -1, sizeof(head));}void insert(int x, int y){ edge[e].v = y; edge[e].next = head[x]; head[x] = e++;}void tarjan(int u){ int v; instack[u] = 1; st[++top] = u; dfn[u] = low[u] = ++index; for(int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if(instack[v]) low[u] = min(low[u], dfn[v]); } if(dfn[u] == low[u]) { scc++; do { v = st[top--]; instack[v] = 0; fa[v] = scc; }while(v != u); }}void build(){ for(int i = 1; i <= m; i++) { scanf("%d%d", &x[i], &y[i]); x[i]++; y[i]++; if(x[i] > y[i]) swap(x[i], y[i]); } for(int i = 1; i <= m; i++) for(int j = i + 1; j <= m; j++) if((x[i] <= x[j] && y[i] >= x[j] && y[i] <= y[j]) || (x[i] >= x[j] && x[i] <= y[j] && y[i] >= y[j])) { insert(i, j + m); insert(j, i + m); insert(i + m, j); insert(j + m, i); } n = 2 * m;}bool check(){ for(int i = 1; i <= m; i++) if(fa[i] == fa[i + m]) return false; return true;}void solve(){ for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); if(check()) printf("panda is telling the truth...\n"); else printf("the evil panda is lying again\n");}int main(){ scanf("%d%d", &n, &m); init(); build(); solve(); return 0;}
- POJ 3207 2-sat 判断是否有合法解
- POJ 3678 Katu Puzzle 2-sat 判断是否有合法解
- poj 3207(2-sat判断)
- 2-SAT (判断是否有解)——Party ( HDU 3062 )
- POJ 3905Perfect Election 2-sat判断可行解
- POJ 3207 2-sat
- poj 3207 2-sat
- 【2-SAT】POJ 3207
- POJ 3207 2-SAT
- poj 3207 2-sat
- poj 3207 2-SAT
- POJ 3207 2-SAT
- POJ 3207 2-sat
- 判断是否为合法字符
- POJ 3678 Katu Puzzle(2-SAT判断)
- POJ 1094(拓扑排序 + 判断是否有环 + 是否有唯一解)
- POJ 3207 2SAT入门
- POJ-3207(2-SAT)
- Eclipse下导入jar包
- Spring AOP的实现机制
- 手把手教你认识mac图标、制作DMG文件和刻录光盘
- c#学习笔记——2
- 用BAPI创建公司间往来凭证
- POJ 3207 2-sat 判断是否有合法解
- 学习笔记(3):C程序设计(第四版)谭浩强著_第五章~第六章
- 用了ADO.NET 2.0 SQ
- Eclipse常用快捷键
- Winform中怎样在一个窗体中获得另一个窗体中的控件的值?
- hibernate tips
- μCOS-II源码文件之OS_FLAG.C
- 图形界面崩溃的一种解决方案
- Hello, ubuntu: Blog from DELL-1320 ubuntu WLAN network