链接:

BZOJ-2199


题意:

给出 \(n(1\leq n\leq 1000)\) 个点,\(m(1\leq m\leq 4000)\) 个形如:“点 \(a\) 取 \(ca\) 或 点 \(b\) 取 \(cb\),其中 \(ca,cb\in\{'Y','N'\}\)” 的限制。如果没有一组方案满足所有限制,输出"IMPOSSIBLE";否则,可能有多组满足限制的解。对于一个点,如果在所有方案中都取 \('Y'\) 则该点最终答案为 \('Y'\),如果在所有方案中都取 \('N'\) 则该点最终答案为 \('N'\),如果都能取到,则该点最终答案为 \('?'\) ,输出最终 \(n\) 个点的答案。


分析:

我们知道,如果只需要一组答案,那么这就是 2-sat 的模板,但是该题似乎需要求出所有方案?

于是我们回顾使用 tarjan 算法求强连通分量解决 2-set 问题中最后取值的部分。

我们知道一个点的 true 和 false 我们会选择拓扑序较大的,这是因为拓扑序较小的可能会连向拓扑序较大的,而此时我们只能选择拓扑序较大的,不然会出现错误。我们发现这就是某个点必须选择某种取值的情况,即上文"在所有方案中都取XXX",而相对应的,如果无法从拓扑序较小的连向较大的,就说明这两种取值都能取,也就是上文“如果都能取到”的情况了。所以我们的算法思路也就比较清晰了。


算法:

在正常 2-sat 建图,tarjan 求强连通分量后,如果无解,输出"IMPOSSIBLE",否则对强连通分量建图,使用 bfs 判断每个点的两种取值的连通性即可。此时,tarjan 时间复杂度 \(O(n+m)\),bfs \(O(n^2)\) ,将 \(n,m\) 视为同级别,则时间复杂度为 \(O(n^2)\),可以通过此题。


代码:
#include<bits/stdc++.h>
using namespace std;
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=2e3+5;
const int M=8e3+5;
struct edge{
int v,next;
}e[M];
int head[N],en;
void insert(int u,int v){
e[++en].v=v;
e[en].next=head[u];
head[u]=en;
}
int n,m;
int sta[N],low[N],dfn[N],id[N],sum,sign,top;
bool vis[N];
void dfs(int u){
low[u]=dfn[u]=++sign;
vis[u]=true;sta[++top]=u;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(!dfn[v]) dfs(v),low[u]=min(low[u],low[v]);
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
sum++;int i=sta[top--];
while(i!=u){
vis[i]=false;
id[i]=sum;
i=sta[top--];
}
vis[i]=false;
id[i]=sum;
}
}
bool check(){
for(int i=1;i<=n;i++)
if(id[i]==id[i+n])
return false;
return true;
}
struct llmmkk{
int v,next;
}f[M];
int h[N],fn;
void ins(int u,int v){
f[++fn].v=v;
f[fn].next=h[u];
h[u]=fn;
}
bool p[N][N];
int inq[N];
queue<int>q;
void bfs(int s){
memset(inq,0,sizeof(inq));
q.push(s);inq[s]=1;
while(!q.empty()){
int u=q.front();q.pop();p[s][u]=true;
for(int i=h[u];i;i=f[i].next){
int v=f[i].v;
if(!inq[v]) q.push(v);
}
}
}
signed main(){
n=in,m=in;
for(int i=1;i<=m;i++){
int a,b;char ta,tb;
cin>>a>>ta>>b>>tb;
insert(a+(ta=='N')*n,b+(tb=='Y')*n);
insert(b+(tb=='N')*n,a+(ta=='Y')*n);
}
for(int i=1;i<=n<<1;i++)if(!dfn[i])dfs(i);
if(check()){
for(int i=1;i<=n<<1;i++){
for(int j=head[i];j;j=e[j].next){
int v=e[j].v;
if(id[i]!=id[v])ins(id[i],id[v]);
}
}
for(int i=1;i<=n;i++){
int a=id[i],b=id[i+n];
if(!vis[a])bfs(a),vis[a]=1;
if(!vis[b])bfs(b),vis[b]=1;
if(p[a][b]) cout<<'Y';
else if(p[b][a]) cout<<'N';
else cout<<'?';
}
}
else cout<<"IMPOSSIBLE"<<'\n'; return 0;
}
题外话:

一遍过,需要对 2-sat 算法深刻理解,好题!

【BZOJ-2199】奶牛议会的更多相关文章

  1. [BZOJ 2199] 奶牛议会

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2199 [算法] 2-SAT [代码] #include<bits/stdc++ ...

  2. BZOJ 2199: [Usaco2011 Jan]奶牛议会

    2199: [Usaco2011 Jan]奶牛议会 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 375  Solved: 241[Submit][S ...

  3. bzoj 1823: [JSOI2010]满汉全席 && bzoj 2199 : [Usaco2011 Jan]奶牛议会 2-sat

    noip之前学的内容了,看到题竟然忘了怎么建图了,复习一下. 2-sat 大概是对于每个元素,它有0和1两种选择,必须选一个但不能同时选.这之间又有一些二元关系,比如x&y=1等等... 先把 ...

  4. [BZOJ 2199] [USACO11JAN] 大陆议会The Continental Cowngress(2-SAT)

    [BZOJ 2199] [USACO11JAN] 大陆议会The Continental Cowngress(2-SAT) 题面 题面较长,略 分析 考虑把问题转化成一个依赖性问题 我们把每只奶牛投出 ...

  5. C++之路进阶——bzoj2199(奶牛议会)

    F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  gryz2016 Logout 捐赠本站 Notice:由于本OJ ...

  6. 【BZOJ2199】 [Usaco2011 Jan]奶牛议会

    Description 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会.议会以“每头牛 都可以获得自己想要的”为原则,建立了下面的投票系统: M只到场的奶牛 (1 & ...

  7. BZOJ2199: [Usaco2011 Jan]奶牛议会(2-SAT)

    Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 559  Solved: 360[Submit][Status][Discuss] Descriptio ...

  8. BZOJ2199[Usaco2011 Jan]奶牛议会——2-SAT+tarjan缩点

    题目描述 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会.议会以“每头牛 都可以获得自己想要的”为原则,建立了下面的投票系统: M只到场的奶牛 (1 <= M ...

  9. BZOJ2199 奶牛议会 【2-sat】

    BZOJ2199 奶牛议会 Description 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会.议会以"每头牛 都可以获得自己想要的"为原则, ...

  10. 【BZOJ2199】[Usaco2011 Jan]奶牛议会 2-SAT

    [BZOJ2199][Usaco2011 Jan]奶牛议会 Description 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会.议会以“每头牛 都可以获得自己想要 ...

随机推荐

  1. C# 多线程编程之锁的使用【互斥锁(lock)和读写锁(ReadWriteLock)】

    多线程编程之锁的使用[互斥锁(lock)和读写锁(ReadWriteLock)] http://blog.csdn.net/sqqyq/article/details/18651335 多线程程序写日 ...

  2. 通过Kubernetes监控探索应用架构,发现预期外的流量

    大家好,我是阿里云云原生应用平台的炎寻,很高兴能和大家一起在 Kubernetes 监控系列公开课上进行交流.本次公开课期望能够给大家在 Kubernetes 容器化环境中快速发现和定位问题带来新的解 ...

  3. 洛谷P1781——宇宙总统(高精度排序)

    题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竟选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: 第一行为一个整数n,代表竞选 ...

  4. gin 源码阅读(2) - http请求是如何流入gin的?

    推荐阅读: gin 源码阅读(1) - gin 与 net/http 的关系 本篇文章是 gin 源码分析系列的第二篇,这篇文章我们主要弄清一个问题:一个请求通过 net/http 的 socket ...

  5. Jmeter导出测试报告

    测试数据概述 jemter导出数据 另存为导出csv文件 命令行导出 测试报告的作用: 反馈结果 复现问题,所以需要写明测试场景.数据

  6. Java-基础-JDK动态代理

    1. 简介 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 比如:我们在调用 ...

  7. bzoj#4722-由乃【倍增,抽屉原理,bitset】

    正题 题目链接:https://darkbzoj.tk/problem/4722 题目大意 给出一个长度为\(n\)的序列值域为\([0,v)\),要求支持操作 询问一个区间能否找到两个没有交的非空下 ...

  8. P4590-[TJOI2018]游园会【dp套dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P4590 题目大意 给出一个长度为\(m\)的字符串\(s\). 对于每个\(k\in[0,m]\)求有多少个长度为 ...

  9. Unity Event Trigger 事件响应(二维,三维)添加组件

    EventTrigger 上主要的方法有PointerEnter.PointerExit.PointerDown.PointerUp.PointerClick............都会显示在面板上面 ...

  10. UE4技术总结——委托

    UE4技术总结--委托 目录 UE4技术总结--委托 一.定义 二.用法 2.1 声明与调用委托 2.1.1 单播委托 2.1.1.a 声明 2.1.1.b 绑定 2.1.1.c 执行委托 2.1.1 ...