2-Sat问题
二分+2-Sat
判断是否可行
输出字典序最小的解
输出字典序可行解
其实这些都是小问题,最重要的是建图,请看论文。
特殊的建边方式,如果a b是一对,a必须选,那么就是b->a建边。
模板题
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define LL long long
struct node
{
int u,v,next;
}edge[*];
int t,scnt,top;
int first[];
int DFN[];
int Low[];
int Belong[];
int in[],stack[];
void CL()
{
t = top = scnt = ;
memset(first,-,sizeof(first));
memset(DFN,,sizeof(DFN));
}
void add(int u,int v)
{
edge[t].u = u;
edge[t].v = v;
edge[t].next = first[u];
first[u] = t ++;
}
void Tarjan(int u)
{
int v,i;
DFN[u] = Low[u] = ++ t;
in[u] = ;
stack[top++] = u;
for(i = first[u];i != -;i = edge[i].next)
{
v = edge[i].v;
if(!DFN[v])
{
Tarjan(v);
if(Low[u] > Low[v])
{
Low[u] = Low[v];
}
}
else if(in[v] && Low[u] > DFN[v])
{
Low[u] = DFN[v];
}
}
if(DFN[u] == Low[u])
{
scnt ++;
do
{
v = stack[--top];
in[v] = ;
Belong[v] = scnt;
}while(u != v);
}
}
int main()
{
int n,m,a1,a2,c1,c2,i,u,v;
while(scanf("%d%d",&n,&m)!=EOF)
{
CL();
for(i = ;i < m;i ++)
{
scanf("%d%d%d%d",&a1,&a2,&c1,&c2);
u = a1*+c1;
v = a2*+c2;
add(u,v^);
add(v,u^);
}
for(i = ;i < *n;i ++)
{
if(!DFN[i])
{
Tarjan(i);
}
}
for(i = ;i < n;i ++)
{
if(Belong[*i] == Belong[*i+])
break;
}
if(i == n)
printf("YES\n");
else
printf("NO\n");
} return ;
}
论文上的例题,输出字典序。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define LL long long
#define N 8001
int que[*N];
int flag[*N];
int first[*N];
int t,n,num;
struct node
{
int u,v,next;
}edge[];
void CL()
{
t = ;
memset(first,-,sizeof(first));
memset(flag,,sizeof(flag));
}
void add(int u,int v)
{
edge[t].u = u;
edge[t].v = v;
edge[t].next = first[u];
first[u] = t ++;
}
int dfs(int x)
{
int i,v;
if(flag[x] == )
return ;
else if(flag[x] == )
return ;
flag[x] = ;
flag[x^] = ;
que[num++] = x;
for(i = first[x];i != -;i = edge[i].next)
{
v = edge[i].v;
if(!dfs(v)) return ;
}
return ;
}
int judge()
{
int i,j;
for(i = ;i < *n;i ++)
{
if(flag[i]) continue;
num = ;
if(!dfs(i))
{
for(j = ;j < num;j ++)
{
flag[que[j]] = ;
flag[que[j]^] = ;
}
if(!dfs(i^))
return ;
}
}
return ;
}
int main()
{
int m,u,v,i;
while(scanf("%d%d",&n,&m)!=EOF)
{
CL();
for(i = ;i < m;i ++)
{
scanf("%d%d",&u,&v);
u --;
v --;
add(u,v^);
add(v,u^);
}
if(judge())
{
for(i = ;i < *n;i ++)
{
if(flag[i] == ) printf("%d\n",i+);
}
}
else
{
printf("NIE\n");
}
}
return ;
}
输出可行解。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <algorithm>
using namespace std;
#define LL long long
struct node
{
int u,v,next;
}edge[],g[];
int t,scnt,top,T;
int first[];
int DFN[];
int op[];
int Low[];
int Belong[];
int in[],stack[];
int input[];
int flag[];
void CL()
{
T = t = top = scnt = ;
memset(first,-,sizeof(first));
memset(DFN,,sizeof(DFN));
memset(flag,,sizeof(flag));
}
void add(int u,int v)
{
edge[t].u = u;
edge[t].v = v;
edge[t].next = first[u];
first[u] = t ++;
}
void _add(int u,int v)
{
g[T].u = u;
g[T].v = v;
g[T].next = first[u];
first[u] = T ++;
}
void Tarjan(int u)
{
int v,i;
DFN[u] = Low[u] = ++ t;
in[u] = ;
stack[top++] = u;
for(i = first[u];i != -;i = edge[i].next)
{
v = edge[i].v;
if(!DFN[v])
{
Tarjan(v);
if(Low[u] > Low[v])
{
Low[u] = Low[v];
}
}
else if(in[v] && Low[u] > DFN[v])
{
Low[u] = DFN[v];
}
}
if(DFN[u] == Low[u])
{
scnt ++;
do
{
v = stack[--top];
in[v] = ;
Belong[v] = scnt;
}while(u != v);
}
}
void tpsort()
{
queue<int> que;
memset(first,-,sizeof(first));
int i,v,u;
for(i = ;i < t;i ++)
{
u = Belong[edge[i].u];
v = Belong[edge[i].v];
if(u != v)
{
_add(v,u);
input[u] ++;
}
}
for(i = ;i <= scnt;i ++)
{
if(input[i] == ) que.push(i);
}
while(!que.empty())
{
u = que.front();
que.pop();
if(flag[u] == )
{
flag[u] = ;
flag[op[u]] = ;
}
for(i = first[u];i != -;i = g[i].next)
{
v = g[i].v;
if(--input[v] == ) que.push(v);
}
} }
int main()
{
int n,m,i,u,v;
char s1,s2;
while(scanf("%d%d%*c",&n,&m)!=EOF)
{
if(n == &&m == ) break;
CL();
for(i = ;i < m;i ++)
{
scanf("%d%c%*c%d%c%*c",&u,&s1,&v,&s2);
if(s1 == 'w') u = u*;
else u = u* + ;
if(s2 == 'w') v = v*;
else v = v* + ;
if(u != (v^))
{
add(u,v^);
add(v,u^);
}
}
add(,);
for(i = ;i < *n;i ++)
{
if(!DFN[i])
{
Tarjan(i);
}
}
for(i = ;i < n;i ++)
{
if(Belong[*i] == Belong[*i+])
break;
op[Belong[*i]] = Belong[*i+];
op[Belong[*i+]] = Belong[*i];
}
if(i != n)
{
printf("bad luck\n");
continue;
}
tpsort();
int z = ;
for(i = ; i < *n; i++)
{
if(flag[Belong[i]] == && i != )
{
if(z) printf(" ");
z = ;
printf("%d", i/);
if(i% == )
printf("h");
else
printf("w");
}
}
printf("\n");
}
return ;
}
2-Sat问题的更多相关文章
- 多边形碰撞 -- SAT方法
检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...
- 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 ...
- Map Labeler POJ - 2296(2 - sat 具体关系建边)
题意: 给出n个点 让求这n个点所能建成的正方形的最大边长,要求不覆盖,且这n个点在正方形上或下边的中点位置 解析: 当然是二分,但建图就有点还行..比较难想..行吧...我太垃圾... 2 - s ...
- 学习笔记(two sat)
关于two sat算法 两篇很好的论文由对称性解2-SAT问题(伍昱), 赵爽 2-sat解法浅析(pdf). 一些题目的题解 poj 3207 poj 3678 poj 3683 poj 3648 ...
- LA 3211 飞机调度(2—SAT)
https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间 ...
- HIT 1917 2—SAT
题目大意:一国有n个党派,每个党派在议会中都有2个代表, 现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会. 已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委 ...
- 2 - sat 模板(自用)
2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一 POJ 3207 Ikki's Story IV ...
- SAT考试里最难的数学题? · 三只猫的温暖
问题 今天无意中在Quora上看到有人贴出来一道号称是SAT里最难的一道数学题,一下子勾起了我的兴趣.于是拿起笔来写写画画,花了差不多十五分钟搞定.觉得有点意思,决定把解题过程记下来.原帖的图太小,我 ...
- 世界碰撞算法原理和总结(sat gjk)
序言 此文出于作者的想法,从各处文章和论文中,总结和设计项目中碰撞结构处理方法.如有其它见解,可以跟作者商讨.(杨子剑,zijian_yang@yeah.net). 在一个世界中,有多个物体,物体可以 ...
- hdu 4115 (2—SAT)
题意:两个人石头剪刀布,一个人的出法已确定,另一个人的出法有一定约束,某两次要相同或者不同,问你第二个人能否全部都不失败. 思路:根据Bob出的情况,我们可以确定每次Alice有两种方案. R与P,S ...
随机推荐
- ajax跨域解决方案2
配置文件添加: <system.webServer> <httpProtocol> <customHeaders> &l ...
- HTTP连接管理
本文是<HTTP权威指南>读书笔记: 几乎所有的HTTP通信都是通过TCP/IP承载的,当HTTP要传送一些报文时,会以流的形式将报文数据的内容通过一条打开的TCP连接按序传输.因此HTT ...
- ContextMenuStrip 类
表示快捷菜单 命名空间: System.Windows.Forms程序集: System.Windows.Forms(位于 System.Windows.Forms.dll) 继承层次结构 Sy ...
- linux之netstat命令
netstat用于显示各种网络相关的信息,如网络连接,路由表接口状态(interface statistics), masquerade连接,多播成员(Multicast Memberships)等等 ...
- bootstrap validate 实现页面动态验证(formvalidate)
关于基本的bootstrap validate 验证方法外面有许多博客上都有讲解,我就不在过多叙述了.大家也可以去看官网api:http://bv.doc.javake.cn/api/ 今天要说的是动 ...
- 【转】使用Python matplotlib绘制股票走势图
转载出处 一.前言 matplotlib[1]是著名的python绘图库,它提供了一整套绘图API,十分适合交互式绘图.本人在工作过程中涉及到股票数据的处理如绘制K线等,因此将matplotlib的使 ...
- Python 之旅
Python2 之旅: https://funhacks.net/explore-python/ <Python Cookbook>第三版 PYTHON3 http://pyt ...
- MyBatis:统计数量
dao: /** * 统计商家的案例数量 * * @param shopId * @return */ long countByShopId(Long shopId); @Override publi ...
- SQL 基础
创建模式 create schema <schema_name> authorization <username> 没有指定schema_name时默认是用户名 删除模式 dr ...
- 【日记】搭建一个node本地服务器
用node搭建一个本地http服务器.首先了解htpp服务器原理 HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端.HTTP协议采用了请求/响应模型 ...