hdu3715 二分+2sat+建图
2024-09-06 09:47:00
题意:
给你一个递归公式,每多一层就多一个限制,问你最多能递归多少层。
思路:
先分析每一层的限制 x[a[i]] + x[b[i]] != c[i],这里面x[] = 0,1,c[i] = 0,1,2
如果我们把 x[]=0,1想成取或不取,就是基础的关系,那么这个题目就可以直接抽象成2sat问题,然后我们二分去枚举深度,每次根据2sat的结果判断二分走向,我的2sat用的是双深搜的强连通,用那个t打头的也行,随意,这样这个题目就ok了,对了下面总结下2sat的建图吧,这个题目也能用上。
#include<stdio.h>
#include<string.h>
#include<stack> #define N_node 500 + 10
#define N_edge 100000 + 100
using namespace std; typedef struct
{
int to ,next;
}STAR; STAR E1[N_edge] ,E2[N_edge];
int list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,cnt;
int mark[N_node];
int A[11000] ,B[11000] ,C[11000];
stack<int>st; void add(int a ,int b)
{
E1[++tot].to = b;
E1[tot].next = list1[a];
list1[a] = tot; E2[tot].to = a;
E2[tot].next = list2[b];
list2[b] = tot;
} void DFS1(int s)
{
mark[s] = 1;
for(int k = list1[s] ;k ;k = E1[k].next)
if(!mark[E1[k].to]) DFS1(E1[k].to);
st.push(s);
} void DFS2(int s)
{
mark[s] = 1;
Belong[s] = cnt;
for(int k = list2[s] ;k ;k = E2[k].next)
if(!mark[E2[k].to]) DFS2(E2[k].to);
} bool ok(int mid ,int n)
{
memset(list1 ,0 ,sizeof(list1));
memset(list2 ,0 ,sizeof(list2));
tot = 1;
for(int i = 1 ;i <= mid ;i ++)
{
int x = A[i] * 2 ,xx = A[i] * 2 + 1;
int y = B[i] * 2 ,yy = B[i] * 2 + 1;
if(C[i] == 0) add(xx ,y) ,add(yy ,x);
if(C[i] == 1) add(x ,y) ,add(y ,x) ,add(xx ,yy) ,add(yy ,xx);
if(C[i] == 2) add(y ,xx) ,add(x ,yy);
}
memset(mark ,0 ,sizeof(mark));
while(!st.empty()) st.pop();
for(int i = 0 ;i < n * 2 ;i ++)
if(!mark[i]) DFS1(i);
memset(mark ,0 ,sizeof(mark));
cnt = 0;
while(!st.empty())
{
int xin = st.top();
st.pop();
if(mark[xin]) continue;
cnt ++;
DFS2(xin);
}
int mk = 0;
for(int i = 0 ;i < n * 2 && !mk ;i += 2)
if(Belong[i] == Belong[i^1]) mk = 1;
return !mk;
} int main ()
{
int t ,n ,m ,i;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= m ;i ++)
scanf("%d %d %d" ,&A[i] ,&B[i] ,&C[i]);
int low ,mid ,up ,ans = 0;
low = 0 ,up = m;
while(low <= up)
{
mid = (low + up) >> 1;
if(ok(mid ,n))
ans = mid ,low = mid + 1;
else up = mid - 1;
}
printf("%d\n" ,ans);
}
return 0;
}
最新文章
- 实现PHPCMS手机门户的伪静态
- Html.BeginForm
- java中如何将字符串数组转换成字符串(转)
- VS2010安装失败解决办法
- yii2.0 图片上传(摘录)
- ruby libmysqlclient.18.dylib
- Java 操作MySql数据库
- spring中@param和mybatis中@param使用区别
- 批量转换cue文件编码
- CentOS修复“OpenSSL Heartbleed漏洞”方法
- 对XML里的属性或元素进行模糊搜索的方法
- java异常处理——finally相关
- ES6 迭代器和生成器
- Postman 进阶(pre-request scripts&;test script)
- vue 去除前后空格trim
- js计算斐波拉切
- C#通过 “枚举数支持在指定类型的集合上进行简单迭代” 的概念获取List的一种方式
- NOIP2018复赛获奖分数线及名额分配办法
- C#索引器理解
- bzoj 4929: 第三题
热门文章
- BurpSuite生成快捷方式
- pytorch(08)数据模型的读取(2)
- $nextTick解决Vue组件卸载在加载合并的问题
- iOS 面试秘籍全套
- BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】
- 主成分分析 | Principal Components Analysis | PCA
- python-类的多态的理解
- International Collegiate Programming Contest 2019 Latin American Regional Contests Problem K
- POJ3278_Catch That Cow(JAVA语言)
- 攻防世界 reverse android-app-100