UVA 11294 Wedding(2-sat)
2-sat。不错的一道题,学到了不少。
需要注意这么几点:
1、题目中描述的是有n对夫妇,其中(n-1)对是来为余下的一对办婚礼的,所以新娘只有一位。
2、2-sat问题是根据必然性建边,比如说A与B二选一,那么当不选A时,必然选B。在本题中,我们所能确定的必然性只有一种:当一对通奸者中的一个人出现在新娘的对面时,另一个必须在新娘的同侧。一开始,我每次建的是两条边,即由新娘指向对面的一人,再从这个人,指向与新娘同侧的另一人(语言描述较困难,但我尽量简明的表达出来)。这是一种假设,因为新娘既可能在左边,又可能在右边。但是这不是必然性:“新娘指向对面的一个人”,这条边不存在必然关系。
解决办法:我们假定新娘就在某一侧。那么是否会影响最终结果呢?不会,因为不管在那一侧,只要有正确方案,转换一下方向,总归是成立的。
3、如何确定新娘就在某一侧?
建边的过程,我们假定了新娘的位置,但是并没有确定的在程序中表现出,新娘就在这一侧。
方法:(1)mark[0]=1;明确的表示出新娘已被标记,但需要注意的是,每次dfs标记的是一条链,或者说是以你选择的点为根的一棵树,所以,只是这样做是不够的,需要单独对mark[0]做一次dfs。
(2)如代码中写的,dfs过程中,若是在 dfs(0) 时失败了,那么就return false;不给 dfs(1) 机会。
注意:准确的说,确定了新娘的位置,即确定了“0w”和“0h”的位置,那么所有包含“0w”或“0h”的关系,所建的边都只能有一条。不过删掉约束条件一样能ac,仔细想来,是solve()中if(i==0)return false;的功劳,因为我只允许dfs(0)成功,所以即使建了另一条边,也不会有机会搜的。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<algorithm>
using namespace std; const int MAXN=; int n;
bool mark[MAXN<<];
int S[MAXN<<],c;
vector<int >G[MAXN<<]; void init(int n)
{
for(int i=;i<(n<<);i++)
G[i].clear();
memset(mark,,sizeof(mark));
} void add(int x,int xval,int y,int yval)
{
x=(x<<)+xval;
y=(y<<)+yval;
G[x].push_back(y);
} bool dfs(int x)
{
if(mark[x^]){
return false;
}
if(mark[x]){
return true;
}
S[c++]=x;
mark[x]=true;
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)){
if(i==) //如果新娘在 0 这一侧这一前提不成立,则 no solusion
return false;
while(c>)
mark[S[--c]]=false;
if(!dfs(i+))
return false;
}
}
}
return true;
} int main()
{
int m,a,b;
char x,y;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m)
return ; init(n);
for(int i=;i<m;i++) //固定新娘在 0 这一侧
{
scanf("%d%c %d%c",&a,&x,&b,&y);
if(x=='h'&&y=='h'){
add(a,,b,);
add(b,,a,);
}else if(x=='w'&&y=='w'){
add(a,,b,);
add(b,,a,);
}else if(x=='h'&&y=='w'){
add(a,,b,);
add(b,,a,);
}else if(x=='w'&&y=='h'){
add(a,,b,);
add(b,,a,);
}
} if(solve()){
for(int i=;i<n;i++)
{
if(mark[i<<])
printf("%dw",i);
else
printf("%dh",i);
if(i!=n-)
printf(" ");
}
printf("\n");
}else
printf("bad luck\n");
}
return ;
}
/*
附上一组数据,让我发现了第三个问题
10 10
6h 2w
1h 9w
1w 3w
9w 0h
1h 9h
4h 1w
7h 2w
1h 0h
0h 9w
0h 3h
*/
UVA 11294 Wedding(2-sat)的更多相关文章
- UVA 11294 - Wedding(Two-Set)
UVA 11294 - Wedding 题目链接 题意:有n对夫妻,0号是公主.如今有一些通奸关系(男男,女女也是可能的)然后要求人分配在两側.夫妻不能坐同一側.而且公主对面一側不能有两个同奸的人,问 ...
- uva 509 RAID!(磁盘数据)
来自 https://blog.csdn.net/su_cicada/article/details/80085318 习题4-7 RAID技术(RAID!, ACM/ICPC World Final ...
- UVA 11168 Airport(凸包+直线方程)
题意:给你n[1,10000]个点,求出一条直线,让所有的点都在都在直线的一侧并且到直线的距离总和最小,输出最小平均值(最小值除以点数) 题解:根据题意可以知道任意角度画一条直线(所有点都在一边),然 ...
- UVA 11624 Fire!(广度优先搜索)
题目大意:在一个N*M的迷宫内,J代表某人(只有一个),F代表火(可能不只一个),#代表墙,火每分钟会向四周除了墙以外的地方扩散一层,问人能否在没被火烧到 之前逃出迷宫,若能逃出输出最短时间.很明显的 ...
- UVA 11478 Halum(差分约束)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34651 [思路] 差分约束系统. 设结点u上的操作和为sum[u] ...
- UVA 12263 Rankings(拓扑排序)
给出一个n个数的序列1,然后有m个改动(a, b),在序列2中a跟b在序列中的相对顺序改变.求符合题意的序列2. 题中说道如果一个数的位置不确定,则输出‘?' ,仔细想想,这种情况是不会存在的,因为在 ...
- uva 10288 Coupons (分数模板)
https://vjudge.net/problem/UVA-10288 大街上到处在卖彩票,一元钱一张.购买撕开它上面的锡箔,你会看到一个漂亮的图案. 图案有n种,如果你收集到所有n(n≤33)种彩 ...
- UVa 104 - Arbitrage(Floyd动态规划)
题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&pa ...
- 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 ...
随机推荐
- c++ 枚举 在函数中的应用
#include <iostream> using namespace std; enum RespErrNo { SUCCESS = , INVALID_URL = , INVALID_ ...
- Codeforces Round #352 (Div. 2) D. Robin Hood
题目链接: http://codeforces.com/contest/672/problem/D 题意: 给你一个数组,每次操作,最大数减一,最小数加一,如果最大数减一之后比最小数加一之后要小,则取 ...
- redis 资料链接
redis 资料链接 http://blog.nosqlfan.com/html/3537.html
- HTML5 动画引擎 小记
国内: Cocos2d-x js版本 layabox Egret Sirius2D lufylegend.js Fireball 国外: CreateJS(EaselJS.TweenJS)http ...
- Unity3D与iOS的交互设计<ViewController 的跳转>
原地址:http://www.aichengxu.com/article/%CF%B5%CD%B3%D3%C5%BB%AF/28797_12.html Unity3D与iOS的交互设计<View ...
- linux源代码阅读笔记 linux文件系统(二)
上一篇文章说到linux文件系统中分为超级块,inode块,block块.inode块给出文件的权限,修改时间,大小等信息. 但是实际上,文件的数据是存储在block块中的.而inode块中给出了存储 ...
- zju 1037 Gridland(找规律,水题)
题目链接 多写几个案例,根据数据的奇偶性,就能找到规律了 #include<stdio.h> int main() { int t,n,m; double ans; scanf(" ...
- java基础知识回顾之javaIO类---FileWriter和FileReader
FileWriter类的构造方法定义如下: 1.public FileWriter(File file)throws IOException 字符流的操作比字节流操作好在一点,就是可以直接输出字符串了 ...
- lintcode: 有效的括号序列
题目: 有效的括号序列 给定一个字符串所表示的括号序列,包含以下字符: '(', ')', '{', '}', '[' and']', 判定是否是有效的括号序列. 样例 括号必须依照 "() ...
- iOS Container View Controller
一.UIViewController 做iOS开发的经常会和UIViewController打交道,从类名可知UIViewController属于MVC模型中的C(Controller),说的更具体点 ...