POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT)
2015-08-01 18:55
393 查看
Description
平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。
Input
第一行为两个整数n和m表示点数和边数,之后m行每行两个整数a和b表示a和b要连一条边
Output
如果存在可行方案则输出panda is telling the truth…
否则输出the evil panda is lying again
Sample Input
4 2
0 1
3 2
Sample Output
panda is telling the truth…
Solution
2-SAT判定,以要连的边为节点构图判断可行性。如果第i条边和第j条边有交叉,则有对应限制i->~j ~j->i j->~i ~i->j
接下来只需要用tarjan算法求强联通分量并判断是否存在使得布尔公式值为真的一组布尔变量赋值即可
Code
平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。
Input
第一行为两个整数n和m表示点数和边数,之后m行每行两个整数a和b表示a和b要连一条边
Output
如果存在可行方案则输出panda is telling the truth…
否则输出the evil panda is lying again
Sample Input
4 2
0 1
3 2
Sample Output
panda is telling the truth…
Solution
2-SAT判定,以要连的边为节点构图判断可行性。如果第i条边和第j条边有交叉,则有对应限制i->~j ~j->i j->~i ~i->j
接下来只需要用tarjan算法求强联通分量并判断是否存在使得布尔公式值为真的一组布尔变量赋值即可
Code
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<stack> #include<vector> using namespace std; #define maxn 1111 vector<int>g[maxn]; stack<int>st; int n,m,scc,index; int low[maxn],dfn[maxn],instack[maxn],fa[maxn]; int l[2][maxn]; void init()//初始化 { scc=index=0; while(!st.empty())st.pop(); for(int i=0;i<maxn;i++)g[i].clear(); memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); memset(low,0,sizeof(low)); } void tarjan(int u)//求强联通分量 { dfn[u]=low[u]=++index; instack[u]=1; st.push(u); int v,size=g[u].size(); for(int i=0;i<size;i++) { v=g[u][i]; 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(); st.pop(); fa[v]=scc; instack[v]=0; }while(v!=u); } } bool check()//判断可行性 { for(int i=0;i<2*m;i++)//求强联通分量 if(!dfn[i]) tarjan(i); for(int i=0;i<2*m;i+=2) if(fa[i]==fa[i+1]) return false; return true; } int main() { scanf("%d%d",&n,&m); init();//初始化 for(int i=0;i<m;i++) { scanf("%d%d",&l[0][i],&l[1][i]); if(l[0][i]>l[1][i])//保证左节点小于右节点,便于判断两边是否交叉 swap(l[0][i],l[1][i]); for(int j=0;j<i;j++)//限制条件 if(l[0][i]<l[0][j]&&l[0][j]<l[1][i]&&l[1][j]>l[1][i]||l[0][j]<l[0][i]&&l[0][i]<l[1][j]&&l[1][i]>l[1][j]) { g[i<<1].push_back((j<<1)+1); g[(j<<1)+1].push_back(i<<1); g[j<<1].push_back((i<<1)+1); g[(i<<1)+1].push_back(j<<1); } } if(check())//存在可行方案 printf("panda is telling the truth...\n"); else//不存在可行方案 printf("the evil panda is lying again\n"); return 0; }
相关文章推荐
- Java学习二:Javac Java的学习(原创)
- Android核心基础-7.Android 网络通信-5.发送GET、POST请求
- CSS优先级与继承
- hdoj 5120 Intersection 【计算圆环相交面积】
- hdu 5329 Question for the Leader
- SQL 2014 SP1 附加数据库时“create file遇到操作系统错误5拒绝访问”
- ICCMO微信公众账号开发系列(3)CURL模拟登陆教务系统查成绩
- Android内存管理机制
- 如何使用会声会影X7添加视频字幕方法
- 如何使用会声会影X7添加视频字幕方法
- 排序方法总和
- BZOJ 2693: jzptab( 莫比乌斯反演 )
- LA4255 Guess (拓扑排序)
- IOS开发之多线程队列
- POJ 2749 && HDU 1815 Building roads(2-SAT+二分)
- 使用core dump查看程序运行异常
- Java_Web三大框架之Hibernate+jsp+selvect+HQL注册用户
- 经验分享:多屏复杂动画CSS技巧三则
- 解决 Boot Camp 虚拟机升级到 Windows 10 后 Parallels Desktop 不能识别的问题
- Longest Common Prefix