题目链接:

https://codeforces.com/gym/101987

题意:

有长度为$n$的只包含$B,R$的字符串

有m种关系,每个关系说出三个位置的确切字符

这三个位置的字符最多有一个是错的

数据范围:

$1\leq n \leq 5000$

$1\leq m \leq 10000$

分析:

比如给出1B 2R 3B

那么如果1是R,2必须是R,3必须是B

如果2是B,1必须是R,3必须是B

如果3是R,1必须是B,2必须是R

对这些关系建立2—SAT模型

1B的编号为1,1R的编号为1+n

缩点,用tarjin算法把两两互达的点连接在一起,这个联通分量要么全被选择要么全部不选

拓扑排序,从小到大遍历,如果这个点没来过,就标记“选择”,相反点的代表则标记“不选择”,并且传递下去

如果还是没看懂:https://blog.csdn.net/jarjingx/article/details/8521690

AC代码:

#include<bits/stdc++.h>
#define ll long long
#define pic pair<int,char>
using namespace std;
const int maxn=1e4+7;
int low[maxn],tim[maxn],tot,vis[maxn],top,boss[maxn],sk[maxn],pick[maxn],n,dp[maxn];
vector<int>ve[maxn],ve2[maxn];
void tarjin(int x){
tim[x]=low[x]=++tot;//加入递归的时间和最低递归时间
sk[++top]=x;
vis[x]=1;
for(int i=0;i<ve[x].size();i++){
int v=ve[x][i];
if(tim[v]==0){
tarjin(v);
low[x]=min(low[x],low[v]);//对后面产生影响,那么自己也将属于这个联通图
}else if(vis[v])
low[x]=min(low[x],low[v]);//构成环了,当然和他联通呀
}
if(low[x]==tim[x]){
int v;
while(1){
v=sk[top--];//出栈
vis[v]=0;
boss[v]=x;//找到老大了
if(v==x)break;
}
}
}
void dfs(int x){//不选择的标记往后传递
if(pick[x]!=0)return ;
// cout<<x<<" "<<-1<<endl;
pick[x]=-1;
for(int i=0;i<ve2[x].size();i++)
dfs(ve2[x][i]);
}
void tp(){//拓扑排序,这个简单
queue<int>que;
for(int i=1;i<=2*n;i++)
if(boss[i]==i&&dp[i]==0)
que.push(i);
while(que.size()){
int v=que.front();
if(pick[v]==0){
// cout<<v<<" "<<1<<endl;
pick[v]=1;
int w=v;
if(w>n)w-=n;
else w+=n;
dfs(boss[w]);
}
que.pop();
for(int i=0;i<ve2[v].size();i++){
dp[ve2[v][i]]--;
if(dp[ve2[v][i]]==0)que.push(ve2[v][i]);
}
}
}
int main(){
int m;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
pic zz[3];
for(int j=0;j<3;j++){
scanf("%d %c",&zz[j].first,&zz[j].second);
getchar();
}
for(int j=0;j<3;j++){
int v1=zz[j].first,v2=zz[j].first+n;
if(zz[j].second=='B')
swap(v1,v2);
for(int k=j+1;k<3;k++){
int w1=zz[k].first,w2=zz[k].first+n;
if(zz[k].second=='R')
swap(w1,w2);
if(w1!=v1)ve[w1].push_back(v1);//选择了v1就选择w1,这里反向建边
if(v2!=w2)ve[v2].push_back(w2);
}
}
}
for(int i=1;i<=2*n;i++)
if(tim[i]==0)tarjin(i); for(int i=1;i<=n;i++)
if(boss[i]==boss[i+n]){
printf("-1\n");
return 0;
}
for(int i=1;i<=2*n;i++){//缩点后重新建边
for(int j=0;j<ve[i].size();j++){
int a=boss[i],b=boss[ve[i][j]];
if(a!=b){
ve2[a].push_back(b);
dp[b]++;
}
}
} tp();
for(int i=1;i<=n;i++){
if(pick[boss[i]]==-1)
printf("R");
else printf("B");
}
printf("\n");
return 0;
}

  

codeforces gym #101987K -TV ShowGame(2-SAT)的更多相关文章

  1. codeforces gym #102082C Emergency Evacuation(贪心Orz)

    题目链接: https://codeforces.com/gym/102082 题意: 在一个客车里面有$r$排座位,每排座位有$2s$个座位,中间一条走廊 有$p$个人在车内,求出所有人走出客车的最 ...

  2. Codeforces Gym 100269 Dwarf Tower (最短路)

    题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game na ...

  3. codeforces Gym 100286J Javanese Cryptoanalysis (二染色)

    每一单词相邻两个字母,不能同时为元音或者辅音... 各种姿势都可以过:7个for,dp,黑白染色,dfs,并查集.... 最主要的思路就是相邻字母连边,把元音和辅音看成两个集合,那么有连边的两个字母一 ...

  4. CodeForces 450B Jzzhu and Sequences (矩阵优化)

    CodeForces 450B Jzzhu and Sequences (矩阵优化) Description Jzzhu has invented a kind of sequences, they ...

  5. Codeforces Gym 101480C - Cow Confinement(扫描线+线段树)

    题面传送门 题意: 有一个 \(10^6\times 10^6\) 的地图.其中 \(m\) 个位置上有花,\(f\) 个矩形外围用栅栏围了起来.保证 \(f\) 个矩形两两之间没有公共点. \(q\ ...

  6. Codeforces Gym100502H:Clock Pictures(KMP算法)

    http://codeforces.com/gym/100502/attachments 题意:有两个时钟上面有n个指针,给出的数字代表指针的角度.问能否在某一时刻使得两个时钟的指针重合. 思路:容易 ...

  7. Codeforces 758C:Unfair Poll(思维+模拟)

    http://codeforces.com/problemset/problem/758/C 题意:教室里有n列m排,老师上课点名从第一列第一排开始往后点,直到点到第一列第m排,就从第二列第一排开始点 ...

  8. Codeforces 639E - Bear and Paradox(二分+贪心)

    Codeforces 题目传送门 & 洛谷题目传送门 原来 jxd 作业里也有我会做的题 i 了 i 了 首先这种题目的套路就是先考虑对于一个固定的 \(c\),怎样求出得分最高的策略,而类似 ...

  9. CodeForces 342A Xenia and Divisors (水题)

    题意:给定 n 个数(小于等于7),让你把它分成 m 组,每组有三个数,且满足,a < b < c,并且 a 能整除 b,b 能整除 c. 析:对于这个题,因为题目说了是不大于7的,那么一 ...

随机推荐

  1. (八)Redis之持久化之AOF方式

    一.概念 AOF方式:将以日志,记录每一个操作 优势:安全性相对RDB方式高很多: 劣势:效率相对RDB方式低很多: 二.案例 appendonly no默认关闭aof方式 我们修改成yes 就开启 ...

  2. Java MergeSort

    Java MergeSort /** * <html> * <body> * <P> Copyright 1994-2018 JasonInternational ...

  3. row_number() over()函数基本用法

    简单的说row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW_NUMBER() OVER (ORDER BY xlh DESC) 是先把xlh列降序,再为降序以后的没条xlh记 ...

  4. form-create教程:自定义布局,实现一行多个组件

    本文将介绍form-create如何自定义布局,实现一行多个组件 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组 ...

  5. 脱壳系列—— *加密脱壳(Android使用手册破解)

    作者:i春秋作家HAI_ZHU 0×00 前言 好久没有写文了,要好好开动一下了.很多事情要忙.这篇文章本来很早之前就要写的,但是因为很多事情就拖了很久. 前置内容 HAI_使用手册 知识总结 0×0 ...

  6. selenium小结

    1.selenium基本使用 https://www.cnblogs.com/andy9468/p/8976930.html 2.url发生跳转的处理 https://www.cnblogs.com/ ...

  7. C#基础 结构体、枚举

    一 结构体 结构体(struct)指的是一种数据结构,一个变量组,是一个自定义的集合.通常使用结构体创造新的“属性”,封装一些属性来组成新的类型.   结构体一般定义在Mian函数上面,位于Class ...

  8. Linux高级网络设置——将多个网卡设置成一个网卡

    Linux下可以设置网卡模式 模式0:负载均衡 模式1:主备模式,不提高网络带宽 模式3:多网卡同时发送相同的数据 准备实验环境: Redhat 6.4 企业版64位,最小化安装. 给虚拟机添加网卡 ...

  9. HTML块级元素与行内元素的区别

    块级元素:块级大多为结构性标记 <address>...</adderss> <center>...</center> 地址文字 <h1>. ...

  10. 控制台警告libpng warning: iCCP: known incorrect sRGB profile

    用控制台测试数据的时候,出现的这个问题.虽然只是一个警告但是看着就是不太舒服 ,见下图 弄了好长时间,无意间切换个输入法,原先使用的是QQ输入法 切换成微软五笔以后,竟然好了 好了 好了