HDU 1816 Get Luffy Out *(2-SAT)
http://acm.hdu.edu.cn/showproblem.php?pid=1816
题意:你有2N把钥匙,你的前面按顺序有M个门,每个门有两个锁,现在你必须用这2N把钥匙去开门. 一个门只要一把锁被打开了这个门就可以被打开.且2N把钥匙还有N个配对关系,每一对的两把钥匙i与j,如果用了i钥匙,那么j钥匙永远不能再用.如果用了j钥匙,那么i钥匙永远不能在用.(这里一把钥匙i可能属于多个配对关系,而POJ2723中2N把钥匙是正好被分成了N对,每把钥匙只出现1次)
分析: 本题类似POJ2723:
http://blog.csdn.net/u013480600/article/details/34891151
由于POJ我没用二分做,所以这里我用二分再做一次.
对于2-SAT的图,有两类关系我们需要添加边.
第一类,对于a与b钥匙配对,那么a与b不能同时出现,有:
add(a,0,b,1) add(b,0,a,1)这里a=0 表示用a钥匙.
第二类,对于门上有锁a与b,那么有:
add(a,1,b,0) add(b,1,a,0)a=1 表示不用钥匙a
其实该题直接用POJ2723的代码就能AC,刘汝佳的模板不用修改,可能用tarjan算法需要修改些东西吧?
AC代码: 二分125ms,比直接遍历速度(406ms)要快不少
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=2000+50;
int n,m;
int a[maxn],b[maxn];//每对钥匙
int c[maxn],d[maxn];//每个门上的锁对
struct TwoSAT
{
int n;
vector<int> G[maxn*2];
int S[maxn*2],c;
bool mark[maxn*2];
bool dfs(int x)
{
if(mark[x^1]) return false;
if(mark[x]) return true;
mark[x]=true;
S[c++]=x;
for(int i=0;i<G[x].size();i++)
if(!dfs(G[x][i])) return false;
return true;
}
void init(int n)
{
this->n=n;
for(int i=0;i<2*n;i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
void add_clause(int x,int xval,int y,int yval)
{
x=x*2+xval;
y=y*2+yval;
G[x].push_back(y);
}
bool solve()
{
for(int i=0;i<2*n;i+=2)
if(!mark[i] && !mark[i+1])
{
c=0;
if(!dfs(i))
{
while(c>0) mark[S[--c]]=false;
if(!dfs(i+1)) return false;
}
}
return true;
}
}TS;
bool ok(int mid)
{
TS.init(n);
for(int i=0;i<n/2;i++)
{
TS.add_clause(a[i],0,b[i],1);
TS.add_clause(b[i],0,a[i],1);
}
for(int i=0;i<mid;i++) //注意这里是i<mid,而不是i<m
{
TS.add_clause(c[i],1,d[i],0);
TS.add_clause(d[i],1,c[i],0);
}
return TS.solve();
}
int main()
{
while(scanf("%d%d",&n,&m)==2&&n)
{
n*=2;
for(int i=0;i<n/2;i++) scanf("%d%d",&a[i],&b[i]);
for(int i=0;i<m;i++) scanf("%d%d",&c[i],&d[i]);
int L=0, R=m;
while(R>L)
{
int mid = L+(R-L+1)/2;
if(ok(mid)) L=mid;
else R=mid-1;
}
printf("%d\n",L);
}
return 0;
}
分享到:
相关推荐
2-sat---hdu3062,代码详尽,清晰,格式规范,亲测无误。
华为HLR相关资料,介绍了HLR中的HDU数据库单元原理
ACM HDU 2000->2099 解题报告 ACM HDU 2000->2099 解题报告 ACM HDU 2000->2099 解题报告
示例 1:输出:[1,2,3,7,8,11,12,9,10,4,5,6]输入的多级列表如下图所示:扁平化后的链表如下图:示例 2:输出:[1,3,2]解释:输入
示例 2:输入:n = 10输出:37解释:第 10 天后,总额为 (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37
示例 1:示例 2:解答:大小写转换: n = n ^ 32转小写: n = n | 32转大写: n = n & -33const toLowerCase =
其中一类查询要求 更新 数组 nums 下标对应的值另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和
2016. 增量元素之间的最大差值题目描述:给你一个下标从 0 开始的整数数组 nums ,该数组的大小为 n ,请你计算 nums[j] - nums[i]
从第 1 秒开始,每 一秒最 开始 时,每个数据服务器都会检查它是否收到了主服务器的回复信息(包括新发出信息的回复信息):如果还没收到任何回复信息,那么该服务器
hdu-acm源代码(上百题)hdu-acm源代码、hdu-acm源代码hdu-acm源代码
杭电组合博弈课件
2019 Multi-University Training Contest 4(2019hdu多校第六场数据与标程)
教你小小JAVA爬虫爬到HDU首页(只为学习)-附件资源
hdu 1200 字符串处理。 将本来的字符串回旋摆放 再从上到下输出 我们就找到规律。每2*n是一个循环,然后对每个2*n内的第i和2*n-i-1输出就好了
杭州电子科技大学online judge (hdu)第十一卷 2000 - 2099 题目集 doc 格式的,希望大家喜欢!
可拆卸核心板滤波电容电源指示灯排针复位F103--R10不焊F207--R9不焊第19引脚F103--C4焊0欧姆,C3不焊Tuesday, August 31
HDU的1250,主要是利用高精度加法,但是代码有点繁琐,效率不是很高
排母,核心板接口ADC 电位器扩展接口,预留模拟量Tuesday, August 31, 2021Tuesday, August 31, 2021Tuesday
5 5513873-A • HDU450-72J1FC 4∼128 S.P,NOTE.2 6 5518491-A • HDU450-146J1FC 4∼128 S.P,NOTE.8 7 5518492-A • HDU450-72K1FC 4∼128 S.P,NOTE.9 8 2105845-1 • DUMMY CANISTER 0∼124 9 5513938-A • AC BOX...