HDU 3062 Party(2-sat题模板+tarjan )

题目:

有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?

Input

n: 表示有n对夫妻被邀请 (n<= 1000)
m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1))

在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2
A1,A2分别表示是夫妻的编号
C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫
夫妻编号从 0 到 n -1

Output

如果存在一种情况 则输出YES
否则输出 NO

Sample Input

2
1
0 1 1 1

Sample Output

YES

分析

2-sat详解:https://blog.csdn.net/zeng_jun_yv/article/details/105316871
一道2—SAT的模板题,其实就是建立一个无向图,然后求强连通分量,再看看同一对夫妻是不是在同一个强连通分量里。由对称性解2-SAT问题

AC代码:

/*由对称性解2-SAT问题*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include<algorithm>
using namespace std;
const int N = 2010;
vector<int> vec[N];
int n, m, id, cnt;
int dfn[N], vis[N], low[N], belong[N];
stack<int> s;
void init()
{memset(vis,0,sizeof(vis));memset(dfn,-1,sizeof(dfn));memset(low,-1,sizeof(low));memset(belong,-1,sizeof(belong));id = cnt = 0;while(!s.empty())s.pop();for(int i = 0; i < 2*n; i++)vec[i].clear();
}
void tarjan(int u)
{dfn[u] = low[u] = id++;vis[u] = 1;int sz = vec[u].size();s.push(u);for(int i = 0; i < sz; i++){int v = vec[u][i];if(dfn[v] == -1){tarjan(v);low[u] = min(low[u], low[v]);}else if(vis[v] == 1){low[u] = min(low[u], dfn[v]);}}if(low[u] == dfn[u]){cnt++;while(!s.empty()){int temp = s.top();s.pop();vis[temp]=0;belong[temp]=cnt;if(temp == u)break;}}
}
int main()
{int a,b,c,d;while(~scanf("%d%d", &n, &m)){init();for(int i = 0; i < m; i++){scanf("%d%d%d%d", &a, &b, &c, &d);vec[2*a+c].push_back(2*b+1-d);vec[2*b+d].push_back(2*a+1-c);}for(int i = 0; i < 2*n; i++){if(dfn[i] == -1)tarjan(i);}bool flag = true;for(int i  = 0; i < n; i++){if( belong[2*i] == belong[2*i+1] ){flag=false;break;}}puts(flag?"YES":"NO");}return 0;
}

Tarjan+缩点+拓扑+染色

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std ;
#define M 4000017
#define N 100017
//a<<1 和 (a<<1) + 1。a<<1表示妻子,(a<<1) + 1表示丈夫
//连接某边是为了推出矛盾。x->y表示选x则必须选y
//注意方向
struct node
{int s, t;int nxt;
} e[M];
int n, m;
int idx, ans, tp, cont;
int dfn[N],vis[N],low[N],head[N],st[N],belong[N];void add(int s,int t)
{e[cont].s = s;e[cont].t = t;e[cont].nxt = head[s];head[s] = cont++;
}
void build_grap(int a, int b, int c, int d)//建图
{if(c==0 && d==0)//两个妻子{add(a<<1, (b<<1)+1);add(b<<1, (a<<1) + 1);}else if(c==0 && d==1)//妻子和丈夫{add((a<<1), (b<<1));add((b<<1)+1, (a<<1)+1);}else if(c==1 && d==0)//丈夫和妻子{add((a<<1) + 1, (b<<1) + 1);add(b<<1, a<<1);}else if(c==1 && d==1)//两个丈夫有矛盾{add((a<<1)+1, b<<1);add((b<<1)+1, a<<1);}
}
void tarjan(int u)
{dfn[u] = low[u] = ++idx;vis[u] = 1;st[++tp] = u;int v ;for(int i = head[u]; i != -1; i = e[i].nxt){v = e[i].t ;if(!dfn[v]){tarjan(v) ;low[u] = min(low[u],low[v]);}else if(vis[v])low[u] = min(low[u],dfn[v]);}if(dfn[u] == low[u]){ans++;while(1){v = st[tp--];vis[v] = 0;belong[v] = ans;if(v == u)break;}}
}
bool _2sat()
{memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));idx = tp = ans = 0;for(int i = 0; i < 2*n; i++)if(!dfn[i])tarjan(i) ;for(int i = 0; i < n; i++)if(belong[2*i]==belong[(2*i)^1])//矛盾return false ;return true;
}int main()
{int a, b, c, d;while(~scanf("%d%d",&n,&m)){cont = 0;memset(head,-1,sizeof(head));for(int i = 0; i < m; i++){scanf("%d%d%d%d",&a,&b,&c,&d);//int u, v;//u = a*2+c; v = b*2+d;//add(u, v^1); add(v, u^1);build_grap(a, b, c, d);}if(_2sat())printf("YES\n");elseprintf("NO\n");}return 0 ;
}
/**思路:每对夫妻代表图中一个结点,只有 1、0 两种选择,对于有矛盾的夫妻对,使其不列席,让无矛盾夫妻对的列席即可
对于 m 矛盾关系,设 a、b 两对夫妇存在矛盾:
若第 a 对的妻子与第 b 对的妻子有矛盾(a b 0 0)
则 a 的妻子去了 b 的丈夫必须去,b 的妻子去了 a 的丈夫必须去:<a,0,b,1>、<b,0,a,1>,添边:<a+n,b>,<b+n,a>
若第 a 对的妻子与第 b 对的丈夫有矛盾(a b 0 1)
则 a 的妻子去了 b 的妻子必须去,b 的丈夫去了 a 的丈夫必须去:<a,0,b,0>、<b,1,a,1>,添边:<a+n,b+n>,<b,a>
若第 a 对的丈夫与第 b 对的妻子有矛盾(a b 1 0)
则 a 的丈夫去了 b 的丈夫必须去,b 的妻子去了 a 的妻子必须去:<a,1,b,1>、<b,0,a,0,>,添边:<a,b>,<b+n,a+n>
若第 a 对的丈夫与第 b 对的丈夫有矛盾(a b 1 1)
则 a 的丈夫去了 b 的妻子必须去,b 的丈夫去了 a 的妻子必须去:<a,1,b,0>、<b,1,a,0>,添边:<a,b+n>,<b,a+n>*/
#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6+10;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
struct node
{int to,next;
} node[N*2];
int head[N],tot;
int n,m;
int dfn[N],low[N];
bool vis[N];//标记数组
int scc[N];//记录结点i属于哪个强连通分量
int block_cnt;//时间戳
int sig;//记录强连通分量个数
stack<int> S;
void init()
{tot=0;sig=0;block_cnt=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(scc,0,sizeof(scc));
}
void addnode(int from,int to)
{node[++tot].to=to;node[tot].next=head[from];head[from]=tot;
}
void Tarjan(int x)
{vis[x]=true;dfn[x]=low[x]=++block_cnt;//每找到一个新点,纪录当前节点的时间戳S.push(x);//当前结点入栈for(int i=head[x]; i!=-1; i=node[i].next)   //遍历整个栈{int y=node[i].to;//当前结点的下一结点if(!dfn[y]){Tarjan(y);low[x]=min(low[x],low[y]);}else if(vis[y])low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x])   //满足强连通分量要求{sig++;//记录强连通分量个数while(true)   //记录元素属于第几个强连通分量{int temp=S.top();S.pop();vis[temp]=false;scc[temp]=sig;if(temp==x)break;}}
}
bool twoSAT()
{for(int i=1; i<=2*n; i++) //找强连通分量if(!dfn[i])Tarjan(i);for(int i=1; i<=n; i++)if(scc[i]==scc[i+n])//条件a与!a属于同一连通分量,无解return false;return true;
}
int main()
{while( scanf("%d%d",&n,&m)!=EOF&&(n+m)){init();while(m--){int x,y,xVal,yVal;scanf("%d%d%d%d",&x,&y,&xVal,&yVal);x++;y++;if(xVal==0&&yVal==0) //x为0或y为0{addnode(x+n,y);//x为0,y为1addnode(y+n,x);//y为0,x为1}else if(xVal==0&&yVal==1) //x为0或y为1{addnode(x+n,y+n);//x为0,y为0addnode(y,x);//y为1,x为1}else if(xVal==1&&yVal==0) //x为1或y为0{addnode(x,y);//x为1,y为1addnode(y+n,x+n);//y为0,x为0}else if(xVal==1&&yVal==1) //x为1或y为1{addnode(x,y+n);//x为1,y为0addnode(y,x+n);//y为1,x为0}}bool flag=twoSAT();if(!flag)printf("NO\n");elseprintf("YES\n");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[PAT乙级]1043 输出PATest

给定一个长度不超过 10​4​​ 的、仅由英文字母构成的字符串。请将字符重新调整顺序&#xff0c;按 PATestPATest… 这样的顺序输出&#xff0c;并忽略其它字符。当然&#xff0c;六种字符的个数不一定是一样多的&#xff0c;若某种字符已经输出完&#xff0c;则余下的字符仍按…

Blazor WebAssembly 3.2 正式发布

5月 20日&#xff0c;微软 发布了 Blazor WebAssembly 3.2(https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-now-available/) 。Blazor 是 ASP.NET Core 中的一个新框架&#xff0c;支持使用 C#和 HTML 创建交互式 Web 应用程序。Blazor WebAssembly 使用基于…

android 语音助手官网,breeno语音助手最新版

breeno语音助手最新版是一款手机中的导航软件&#xff0c;在这款软件中你能享受到非常方便的导航体验&#xff0c;这款软件中的指令不需要用户手动去输入&#xff0c;现在只需要你使用的语音就直接能对其进行操控了。感兴趣的用户就来去我下载网进行下载使用吧&#xff01;bree…

[PAT乙级]1047 编程团体赛

编程团体赛的规则为&#xff1a;每个参赛队由若干队员组成&#xff1b;所有队员独立比赛&#xff1b;参赛队的成绩为所有队员的成绩和&#xff1b;成绩最高的队获胜。 现给定所有队员的比赛成绩&#xff0c;请你编写程序找出冠军队。 输入格式&#xff1a; 输入第一行给出一个…

2-SAT适定性(Satisfiability)问题知识点详解

SAT是适定性(Satisfiability)问题的简称。一般形式为k-适定性问题&#xff0c;简称 k-SAT。而当k>2时该问题为NP完全的&#xff0c;所以我们只研究k2时情况。 2-SAT问题 现有一个由N个布尔值组成的序列A&#xff0c;给出一些限制关系&#xff0c;比如A[x] AND A[y]0、A[x]…

温故知新:Docker基础知识知多少?

【云原生】| 作者/Edison Zhou这是恰童鞋骚年的第233篇原创文章记得之前曾经粗略的写过一篇Docker的基础及ASP.NET Core部署Docker示例的入门文章&#xff0c;但那个时候刚刚学习对Docker的认知还比较浅&#xff0c;现在重新来温故知新一下。本文预计阅读时间为10min。1容器的用…

自动备份html文件,windows下定期自动备份本地文件(文件夹)

虽然网上有一些免费的文件自动备份软件&#xff0c;但是没有自己编写一段批处理来完成备份任务来的放心&#xff0c;而且不用占用系统资源。就给大家讲一下如何利用批处理完成本地文件或者文件夹的备份。1、批处理脚本该方法可把某文件夹下的文件同步到另外的文件夹&#xff0c…

Dreamoon and Ranking Collection CodeForces - 1330A (贪心)

题意&#xff1a; 大意就是给一个序列&#xff0c;可能有重复数字&#xff0c;有x次机会为这个序列填上一个数字&#xff0c;问最终从里面获得的1~v连续子序列的v最大是多少。 题目: Dreamoon is a big fan of the Codeforces contests. One day, he claimed that he will …

[C++11]lambda表达式语法

代码如下: #include <iostream> using namespace std;void func(int x, int y) {int a;int b;[]() {int c a;//使用了外部变量&#xff0c;[]里面加个 int d x;}; }int main() {return 0; }lambda表达式的注意事项: 以上图片来自下面链接: https://subingwen.cn/cpp…

[翻译]欢迎使用C#9.0

本文由公众号[开发者精选资讯](微信号&#xff1a;yuantoutiao)翻译首发&#xff0c;转载请注明来源C# 9.0 is taking shape, and I’d like to share our thinking on some of the major features we’re adding to this next version of the language.C&#xff03;9.0初具规…

android环境搭建出错,androidstudio配置环境遇到的各种错误(持续更新中)

AndroidStudio3.0,gradle4.1&#xff0c;新建工程&#xff0c;遇到如下错误&#xff1a;Error:Unable to resolve dependency for :appdebugAndroidTest/compileClasspath: Could not resolve com.android.support.test:runner:1.0.1.Error:Unable to resolve dependency for :…

操作系统第四章习题

操作系统第四章习题 1.对一个将页表放在内存中的分页系统&#xff1a; (1) 如果访问内存需要0.2μs&#xff0c;有效访问时间为多少? (2) 如果加一快表&#xff0c;且假定在快表中找到页表的几率高达90%&#xff0c;则有效访问时间又是多少&#xff08;假定查快表需花的时间…

[C++11]右值和右值引用

代码如下: #include <iostream> using namespace std;int main() {//左值int num 9;//左值引用int &a num;//右值const int N 5;//右值引用int && b 8;//常量左值引用const int &c num;//常量右值引用const int &&d 6;//const int &&…

用html写出生日蛋糕,纯HTML5+CSS3制作生日蛋糕代码

.birthday .container{width:600px;height:600px;margin:0px auto;background: #fafafa;border-radius:5px;position: relative;}/**** 顶层的**/.birthday .top-one{position: absolute;width:280px;height: 280px;bottom: 200px;left:160px;}.birthday .top-one .bottom{posi…

我们为什么推荐在Json中使用string表示Number属性值

在这篇简短的文章中&#xff0c;我将解释在使用JSON传输数据时&#xff0c;为什么浮点数或大十进制值应表示为字符串 。long类型引发的诡异情况长话短说&#xff0c;同事在利用swagger对接后端API时&#xff0c;诡异的发现swaggerUI中显示的json属性值并不是api返回的值。[Http…

并查集+基础知识点详解

并查集概念 并查集单看名字大家也能猜到这个算法的作用&#xff0c;是用来对集合进行合并和查找操作 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。——来自百度百科 就是将原本不一样的集合&#xff0c;但是由于某种关系有…

[C++11]move资源的转移

从实现上讲&#xff0c;std::move 基本等同于一个类型转换&#xff1a;static_cast<T&&>(lvalue);&#xff0c;函数原型如下: template<class _Ty> _NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) _NOEXCEPT { …

网址导航html5源码图标版,最新仿hao123网址导航(晓风网址导航系统) v4.2

使用说明 采用aspaccess架构&#xff0c;简单易用 access数据库已做防下载处理&#xff0c;安全放心 程序不能放到子目录&#xff0c;否则无法生成全站 上传程序进入后台设置一下网站信息&#xff0c;生成所有HTML页面 首页网站标志LOGO目录位置&#xff1a;/images/logo_140.g…

基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型

上一篇文章使用自定义仓储完成了简单的增删改查案例&#xff0c;有心的同学可以看出&#xff0c;我们的返回参数一塌糊涂&#xff0c;显得很不友好。在实际开发过程中&#xff0c;每个公司可能不尽相同&#xff0c;但都大同小异&#xff0c;我们的返回数据都是包裹在一个公共的…

奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革&#xff1a;重新分配房子。 这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住&#xff08;如果有老百姓没房子住的话&#xff0c;容易引起不安定因素&…