loj 1251(2-sat + 输出一组可行解)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26961
思路:u表示留下,~u表示离开,同理v,对于+u,-v,我们可以这样来定义:若u离开,则v必须留下,如v离开,则u必须留下,于是我们可以连边u+n->v,v+n->u,后面的同理。
![](/assets/blank.gif)
![](/assets/blank.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #include<vector> 7 #include<queue> 8 using namespace std; 9 #define MAXN 20000 10 #define MAXM 444444 11 12 struct Edge{ 13 int v,next; 14 }edge[MAXM]; 15 16 int n,m,NE; 17 int head[MAXN]; 18 19 void Insert(int u,int v) 20 { 21 edge[NE].v=v; 22 edge[NE].next=head[u]; 23 head[u]=NE++; 24 } 25 26 int cnt,bcc_count; 27 int low[MAXN],dfn[MAXN],color[MAXN]; 28 bool mark[MAXN]; 29 stack<int>S; 30 31 void Tarjan(int u) 32 { 33 low[u]=dfn[u]=++cnt; 34 mark[u]=true; 35 S.push(u); 36 for(int i=head[u];i!=-1;i=edge[i].next){ 37 int v=edge[i].v; 38 if(dfn[v]==0){ 39 Tarjan(v); 40 low[u]=min(low[u],low[v]); 41 }else if(mark[v]){ 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 if(low[u]==dfn[u]){ 46 int v; 47 bcc_count++; 48 do{ 49 v=S.top(); 50 S.pop(); 51 mark[v]=false; 52 color[v]=bcc_count; 53 }while(u!=v); 54 } 55 } 56 57 int opp[MAXN]; 58 bool Judge() 59 { 60 for(int i=1;i<=n;i++){ 61 if(color[i]==color[i+n])return false; 62 //opp[x]保存的是和编号为x的连通分量矛盾的连通分量的编号 63 opp[color[i]]=color[i+n]; 64 opp[color[i+n]]=color[i]; 65 } 66 return true; 67 } 68 69 vector<vector<int> >g; 70 vector<int>ans; 71 int degree[MAXN]; 72 int vis[MAXN]; 73 74 void TopSort() 75 { 76 queue<int>que; 77 for(int i=1;i<=bcc_count;i++){ 78 if(degree[i]==0)que.push(i); 79 } 80 while(!que.empty()){ 81 int u=que.front(); 82 que.pop(); 83 if(vis[u]==0){ 84 //染色 85 vis[u]=1; 86 vis[opp[u]]=-1; 87 } 88 for(int i=0;i<g[u].size();i++){ 89 degree[g[u][i]]--; 90 if(degree[g[u][i]]==0)que.push(g[u][i]); 91 } 92 } 93 } 94 95 96 int main() 97 { 98 int _case,t=1,a,b,u,v; 99 scanf("%d",&_case); 100 while(_case--){ 101 scanf("%d %d",&m,&n); 102 NE=0; 103 memset(head,-1,sizeof(head)); 104 while(m--){ 105 scanf("%d%d",&a,&b); 106 u=abs(a),v=abs(b); 107 if(a>0&&b>0)Insert(u+n,v),Insert(v+n,u); 108 else if(a>0&&b<0)Insert(u+n,v+n),Insert(v,u); 109 else if(a<0&&b>0)Insert(u,v),Insert(v+n,u+n); 110 else Insert(u,v+n),Insert(v,u+n); 111 } 112 cnt=bcc_count=0; 113 memset(mark,false,sizeof(mark)); 114 memset(dfn,0,sizeof(dfn)); 115 memset(color,0,sizeof(color)); 116 for(int i=1;i<=2*n;i++)if(dfn[i]==0)Tarjan(i); 117 printf("Case %d: ",t++); 118 if(!Judge()){ 119 puts("No"); 120 continue; 121 } 122 puts("Yes"); 123 //反向建图 124 memset(degree,0,sizeof(degree)); 125 g.clear(); 126 g.resize(2*n+2); 127 for(int u=1;u<=2*n;u++){ 128 for(int i=head[u];i!=-1;i=edge[i].next){ 129 int v=edge[i].v; 130 if(color[u]!=color[v]){ 131 g[color[v]].push_back(color[u]); 132 degree[color[u]]++; 133 } 134 } 135 } 136 memset(vis,0,sizeof(vis)); 137 TopSort(); 138 ans.clear(); 139 for(int i=1;i<=n;i++){ 140 if(vis[color[i]]==1)ans.push_back(i); 141 } 142 printf("%d",(int)ans.size()); 143 sort(ans.begin(),ans.end()); 144 for(int i=0;i<(int)ans.size();i++){ 145 printf(" %d",ans[i]); 146 } 147 puts(""); 148 } 149 return 0; 150 }
View Code
转载于:https://www.cnblogs.com/wally/p/3335713.html
loj 1251(2-sat + 输出一组可行解)相关推荐
- POJ 3683 【2-sat+求一组可行解】.cpp
题意: 有一个牧师要给好几对新婚夫妇准备婚礼.. 已知每对新婚夫妇的有空的时间以及婚礼持续时间.. 问是否可以让每对新婚夫妇都得到该牧师的祝福~ 如果可以就输出YES以及可行解 不可以就输出NO 输入 ...
- Linux命令 —— 输出一组系统信息(uname -a)
目录 执行结果显示: 查看uname的用法: 将每个参数都重新执行一次: 执行结果显示: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
- FOR循环及基础应用方式(输出一组字符串)
for循环写法: for(起始状态;判断条件;状态改变){ 执行语句; } 运行方式: 1.判断条件 2.执行语句 3.状态改变 for(var i = 0; i < 3; i++) { ale ...
- C语言:输出一组数的最大值与最小值
C语言:输出一组数中的最大值或最小值 如果要输出多个数的最大值只需更改数组大小与循环的限制条件即可 这里以三个数为例: 最大值 #include<stdio.h> int main() { ...
- (C语言)实现函数逆序输出一组数据
实现函数逆序输出一组数据 题目:函数实现将输入的一组数据逆序输出的功能.(参考函数原型:void isort(int a[], int n)) 输入输出格式要求: 编写函数void isort(int ...
- java编写统计玩家总数的程序_JAVA程序:输出一组数后如何统计特定数的总数
题目:定义一个int型的一维数组,包含40个元素,用来存储每个学员的成绩,循环产生40个0~100之间的随机整数,将它们存储到一维数组中,然后统计成绩低于平均分的学员的人数,并输出出... 题目:定义 ...
- 【C语言】(数组方式)输出一组成绩中的最高分与最低分
两种不同方式获取最大值与最小值 代码1: #include <stdio.h> int main() {float score[5], sum = 0, max, min;int i;pr ...
- 鸡和兔关在一个笼子里,鸡有2只脚,兔有4只脚,没有例外。已知现在可以看到笼子里m个头和n只脚,求鸡和兔子各有多少只?(输出一组数据)
#include<stdio.h> int main() { int m,n; //m个头,n个脚. int x,y; //x只鸡,y只兔 ...
- C语言 输出一组数中的最大值
数组中给定十个数字,首先让第一个数是最大的数,与之后的数进行比较,得到下一个最大的数,在与下一个数比较. #include <stdio.h> int main() {int a[10] ...
最新文章
- 如何进行app的兼容性测试?需要考虑哪些方面?
- Python学习笔记:电子邮件,POP3收取邮件
- OpenCASCADE:Foundation Classes库组织
- Docker和宿主机操作系统文件目录互相隔离的实现原理
- 闲话WPF之十(Dependency属性 [2] )
- linux分析目录内存,在 Linux x86-64 模式下分析内存映射流程
- 依赖注入(DI)入门
- cmd使用conda建立python虚拟环境
- Linux 设备驱动的固件加载-转载
- 卷积的发展历程,原理和基于 TensorFlow 的实现
- 微信小程序系列(3)如何用微信小程序写一个论坛?贴心代码详解(一)发帖
- Python安装和环境配置
- 局域网传文件_安卓用户福音!让文件传输摆脱数据线的束缚,自由穿梭
- 文件夹怎么打包压缩?压缩包太大如何缩小?
- gradient设置上下渐变_CSS3 经典教程系列:CSS3 线性渐变(linear-gradient)
- TFN FMT800 系列矢量网络分析仪技术评测
- Win10搭建我的世界Minecraft服务器「内网穿透远程联机」
- PEWIN32 PRO site key
- 正式揭牌!华为与清华北大、中科院共建博士后工作站!
- 某学生的记录由学号、5门课程成绩和平均分组成,学号和5门课程的成绩已在主函数中给出。请编写函数fun,它的功能是:求出该学生的平均分,并放在记录的ave成员中。
热门文章
- 函数使用了堆栈的字节超过_单片机地址空间,堆栈理解
- 计算机一级查找同类型文件,如何快捷找出电脑内的重复文件
- Git/Github--push自己的第一段代码
- 每天一道LeetCode-----使用最少的操作将一个字符串转换成另一个字符串,只有插入,删除,替换三种操作
- Openstack dnsmasq配置域名解析
- pytorch中的批量归一化BatchNorm1d和BatchNorm2d的用法、原理记录
- c++primer书上习题date类的部分源代码(待整理)
- 3.2 python实战_线性回归的梯度下降法
- 一分钟带你看懂UML图
- 31.1 inforMATION_SCHEMA aCcess syntax