2-SAT相关

什么是2-SAT?

       其实2-SAT,就是有很多组人,每组有只有两个成员,要你从每组中选一个人。其中,有一些人有矛盾不能同时选。如果抽象的说,就是有n个集合,每个集合有两个元素,从每个集合中选出一个元素,其中有一些元素不能同时选。判定是否有一种方案可以满足上列的条件。

2-SAT的主要问题?

  是否有解,如果有解给出一组可行解,有时有要求字典序最小的解。

主要算法

  对这类问题进行构造建图。下面进行一些约定:我们把假定有i 组人,第i组的两个成员分别为Ai 和 Ai'。如果要选Ai就必须选Aj,那么就把 Ai  指向 Aj。如果Ai和Aj有矛盾,则选Ai 就必须选Aj',选Aj 就必须选Ai'。特别的,如果Ai 和 Ai'中,一定不选Ai,就连一条由Ai指向Ai'的边。2-SAT问题可以转为求有向图的强连通分量和拓扑排序(具体见 由对称性解2-SAT问题)。

下面是算法的步骤:

    1、根据题意建图
    2、求强连通分量( 这有一篇大神写的强连通分量的文章)
    3、拓扑求可行解

算法的模板:

如果有n组人,有m条边那么下面算法的效率为O(m)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//如果不求方案数就要把下面这句删掉
#define REQUE_COLOR 1

//writen by nothi

#ifdef  REQUE_COLOR
const int RED = 1;
const int BULE = 2;
const int WHITE = 0;
#endif

const int maxn = 1100;
//顶点的个数,这里的顶点个数实际上就是组的个数
//组的编号从0到n-1
const int maxn2 = maxn*2;
const int maxm = maxn*maxn;//边的条数

typedef struct Edge{
	int s;
	int e;
	int next;
}Edge;

typedef struct Adj{
	int edge_sum;
	int head[maxn2];
	Edge edge[maxm];

	void initial(){	
		edge_sum = 0;
		memset(head,-1,sizeof(head));
	}

	void add_edge(int a, int b){
		edge[edge_sum].s = a;
		edge[edge_sum].e = b;
		edge[edge_sum].next = head[a];
		head[a] = edge_sum++; 
	} 
}Adj;

#ifdef  REQUE_COLOR
Adj op_adj;
#endif

//顶点序号(组的编号)从0到n-1
//编号为i的组,在实际的算法中组员是2*i 和 2*i+1
//所以对于组员i,和它同组的另一个组员为i^1
//color[belong[u]] == RED 是解
//选调用initial()初始化,再用solve()解决问题
//如果要求一组可行解,调用creat();
typedef struct Two_sat{
	int n;//n是顶点数

	Adj *adj;
	Edge *e;
	int *head;
	int top, cnt, cur;
	int dfn[maxn2];
	int low[maxn2];
	int stack[maxn2];
	int belong[maxn2];	
	int instack[maxn2];

	void initial(Adj* _adj,int _n){
		n = _n;
		adj = _adj;
		e = (*adj).edge;
		head = (*adj).head;
	}

	bool check(){	
		int i, j;
		tarjan();
		for(i = 0; i < 2*n; i += 2)
			if(belong[i] == belong[i^1])
				return false;
		return true;
	}

	int min(int a, int b){
		if(a < b) return a;
		else return b;
	}

	void tarjan(int i){
		int j = head[i];

		dfn[i] = low[i] = ++cur;

		instack[i] = 1;
		stack[top++] = i;

		while(j != -1){
			int u = e[j].e;
			if       (dfn[u] == -1){
				tarjan(u);
				low[i] = min(low[i],low[u]);
			}else if (instack[u])
				low[i] = min(low[i],dfn[u]);
			j = e[j].next; 
		}

		if(dfn[i] == low[i]){
			++cnt;		
			do{
				j = stack[--top];
				instack[j] = 0;
				belong[j] = cnt;
			}while(j != i);
		}
	}

	void tarjan(){
		int i, j;
		cur = cnt = top = 0;
		memset(dfn,-1,sizeof(dfn));
		for(i = 0; i < 2*n; i++)	
			if(dfn[i] == -1)
				tarjan(i);
	}
		
       #ifdef REQUE_COLOR
       //求具体的方案
       int opp[maxn2];
       int color[maxn2];
       int indegree[maxn2];
       
       void creat(){
	       int u, v, i, j;
	       memset(indegree,0,sizeof(indegree));
	       op_adj.initial();

	       for(i = 0; i < 2*n; i += 2){
		       opp[belong[i]] = belong[i^1];
		       opp[belong[i^1]] = belong[i];
	       }

	       for(i = 0; i < (*adj).edge_sum; i++){
			u = belong[e[i].s];
			v = belong[e[i].e];
			if(u == v) continue;
			++indegree[u];
			op_adj.add_edge(v,u);
	       }

	       toposort();
       }

       void toposort(){ 
	       int *head1 = op_adj.head;
	       Edge *edge = op_adj.edge;
	       int i, j, p, now, head, tail,next;

	       head = tail = 0;
	       memset(color,WHITE,sizeof(color));
	       for(i = 1; i <= cnt; i++)
		       if(!indegree[i])
				stack[++head] = i;

	      	while(head != tail){ 
			now = stack[++tail];
			if(color[now] != WHITE)	continue;

		        color[now] = RED;
			color[opp[now]] = BULE;

			p = head1[now];
			while(p != -1){
				next =edge[p].e;	
				--indegree[next];
				if(indegree[next] == 0){
					stack[++head] = next;
				}
				p = edge[p].next;
			}
		}
       }
       #endif
}Two_sat;

Adj adj;
Two_sat ts;




相关问题:

直接的判定问题:
   hdu-1824
         hdu-3602
         hdu-4115
         poj-3678
       
二分答案+2-SAT:
        hdu-1815
        hdu-1816
        hdu-3622
        hdu-3715
        poj-2296
        poj-3207
       
求一组可行解:
        poj-3648
        poj-3683
        poj-3905

求字典序最小的方案:
       hdu-1814
      这题可以看  这里


 转载请注明出处--nothi

下载前可以先看下教程 https://pan.quark.cn/s/a426667488ae 标题“仿淘宝jquery图片左右切换带数字”揭示了这是一个关于运用jQuery技术完成的图片轮播机制,其特色在于具备淘宝在线平台普遍存在的图片切换表现,并且在整个切换环节中会展示当前图片的序列号。 此类功能一般应用于电子商务平台的产品呈现环节,使用户可以便捷地查看多张商品的照片。 说明中的“NULL”表示未提供进一步的信息,但我们可以借助标题来揣摩若干核心的技术要点。 在构建此类功能时,开发者通常会借助以下技术手段:1. **jQuery库**:jQuery是一个应用广泛的JavaScript框架,它简化了HTML文档的遍历、事件管理、动画效果以及Ajax通信。 在此项目中,jQuery将负责处理用户的点击动作(实现左右切换),并且制造流畅的过渡效果。 2. **图片轮播扩展工具**:开发者或许会采用现成的jQuery扩展,例如Slick、Bootstrap Carousel或个性化的轮播函数,以达成图片切换的功能。 这些扩展能够辅助迅速构建功能完善的轮播模块。 3. **即时数字呈现**:展示当前图片的序列号,这需要通过JavaScript或jQuery来追踪并调整。 每当图片切换时,相应的数字也会同步更新。 4. **CSS美化**:为了达成淘宝图片切换的视觉效果,可能需要设计特定的CSS样式,涵盖图片的排列方式、过渡效果、点状指示器等。 CSS3的动画和过渡特性(如`transition`和`animation`)在此过程中扮演关键角色。 5. **事件监测**:运用jQuery的`.on()`方法来监测用户的操作,比如点击左右控制按钮或自动按时间间隔切换。 根据用户的交互,触发相应的函数来执行...
垃圾实例分割数据集 一、基础信息 • 数据集名称:垃圾实例分割数据集 • 图片数量: 训练集:7,000张图片 验证集:426张图片 测试集:644张图片 • 训练集:7,000张图片 • 验证集:426张图片 • 测试集:644张图片 • 分类类别: 垃圾(Sampah) • 垃圾(Sampah) • 标注格式:YOLO格式,包含实例分割的多边形点坐标,适用于实例分割任务。 • 数据格式:图片文件 二、适用场景 • 智能垃圾检测系统开发:数据集支持实例分割任务,帮助构建能够自动识别和分割图像中垃圾区域的AI模型,适用于智能清洁机器人、自动垃圾桶等应用。 • 环境监控与管理:集成到监控系统中,用于实时检测公共区域的垃圾堆积,辅助环境清洁和治理决策。 • 计算机视觉研究:支持实例分割算法的研究和优化,特别是在垃圾识别领域,促进AI在环保方面的创新。 • 教育与实践:可用于高校或培训机构的AI课程,作为实例分割技术的实践数据集,帮助学生理解计算机视觉应用。 三、数据集优势 • 精确的实例分割标注:每个垃圾实例都使用详细的多边形点进行标注,确保分割边界准确,提升模型训练效果。 • 数据多样性:包含多种垃圾物品实例,覆盖不同场景,增强模型的泛化能力和鲁棒性。 • 格式兼容性强:YOLO标注格式易于与主流深度学习框架集成,如YOLO系列、PyTorch等,方便研究人员和开发者使用。 • 实际应用价值:直接针对现实世界的垃圾管理需求,为自动化环保解决方案提供可靠数据支持,具有重要的社会意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值