SS241006B. 结论题

news/2024/10/6 16:35:36/文章来源:https://www.cnblogs.com/liyixin0514/p/18449045

SS241006B. 结论题

题意

给你一个无向图,每个点有点权 \(1 \le a_i \le 10^6\) 和颜色 \(c_i=0/1\)。可以进行若干次操作:选择任意一条边,交换两个点的点权,如果两个点的颜色相同,两个点的颜色分别取反。给出初始状态和一个终态,判断是否存在到达终态的方案。

思路

真结论题。

这个操作非常恶心。巧妙地转化一下可以变成每次选定一条边,交换点权和颜色,然后对颜色取反。然后我们发现这个操作是可逆的。

考虑二分图怎么做。

首先原图可以分成若干个连通块分别做。

对于一个连通块,因为它是连通的,类似冒泡排序,所以点权是可以任意排序的,但是颜色还有取反操作。

对于二分图,一个左部的点如果换到了左部,颜色不变,换到了右部,颜色取反。

所以对于每个点,我们记录一个二元组 \((点权,点在左部时的颜色)\),对初态和终态都做这样的记录。如果初态和终态的元素相同,就一定有可行方案。对于初态的某个二元组和终态的某个二元组的一对匹配,如果在终态的原图,这个二元组在右部,那么初态的那个二元组也移到右部对应位置就行,这是可以一一匹配的。因为这是一个连通块,所以可以任意排序,因此结论成立。

对于非二分图的情况。结论是,初态点权和终态点权集合相同,且初态原图颜色 \(0\) 和终态原图颜色 \(0\) 的个数奇偶性相同(\(1\) 也一样)。必要性显然。下面证明其充分性。

首先我们在原图随便找一个生成二分图,比如找一个生成树。然后对每个点维护上面提到的二元组 \((点权,点在左部时的颜色)\)。由上面的结论可以知道,如果初态的二元组集合和终态相同,就一定有可行的方案。也就是说,在这个二分图上面我们可以任意排序这些二元组同时不改变它们的值。

原图就是二分图上加上了若干条边,如果在不同部加边(生成树奇数层和偶数层连边),图还是一个二分图,没有新的性质。如果在生成树奇数和奇数(或偶数和偶数)层连边,就出现了奇环。

类似冒泡排序,在这个奇环上所有点的点权可以任意排序,其实不需要再奇环上面排序,如果在二分图的路径上,不仅也可以任意排序,而且二元组的 \(点在左部的颜色\) 这个值还不会改变。现在证明之前那个结论的充分性。我们可以通过二分图上的路径把两个颜色相同的点放到非二分图的那条边的两个端点,然后交换它们,并取反颜色,这样某个颜色的总数就会 \(-2\) 了。而且我们只需要一个奇环,因为你可以把整棵生成树的点任意排序,把你想要改变颜色的点颜色取反。因此利用某一个奇环做若干次颜色取反,就可以使初态和终态二元组的集合相同了,然后由于二分图可以任意排序二元组,所以结论充分。

证毕。

code

#include<bits/stdc++.h>
//#define LOCAL
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
const int N=1e5+7;
template <typename T>
inline void read(T &x) {x=0;T fl=1;char ch=getchar();for(;!isdigit(ch);ch=getchar()) if(ch=='-') fl=-1;for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';x=x*fl;
}
template <typename T>
inline void write(T x,char ch) {static int st[10];int top=0;if(x<0) putchar('-'),x=-x;do {st[top++]=x%10;x/=10;}while(x);while(top) putchar(st[--top]+'0');putchar(ch);
}
int T,n,m;
vector<int> to[N];
int vi[N];
int u,v;
char ch[N];
typedef pair<int,int> pii;
#define fi first
#define se second
pii s[N],t[N];
bool checkeft(int &cs,int &ct,vector<pii> &vecs,vector<pii> &vect,int u) {bool ans=1;if(s[u].se) cs++;if(t[u].se) ct++;if(vi[u]==2) s[u].se^=1,t[u].se^=1;vecs.push_back(s[u]);vect.push_back(t[u]);for(int v:to[u]) {if(!vi[v]) vi[v]=(vi[u]==1?2:1),ans&=checkeft(cs,ct,vecs,vect,v);else if(vi[u]==vi[v]) ans=0;}return ans;
}
int main() {#ifdef LOCALfreopen("in.txt","r",stdin);freopen("my.out","w",stdout);#elsefreopen("graph.in","r",stdin);freopen("graph.out","w",stdout);#endifread(T);while(T--) {read(n),read(m);rep(i,1,m) {read(u),read(v);to[u].push_back(v),to[v].push_back(u);}rep(i,1,n) read(s[i].fi);sf("%s",ch+1);rep(i,1,n) s[i].se=(ch[i]=='R'?1:0);rep(i,1,n) read(t[i].fi);sf("%s",ch+1);rep(i,1,n) t[i].se=(ch[i]=='R'?1:0);bool ans=1;rep(k,1,n) {if(!ans) break;if(vi[k]) continue;vector<pii> vecs,vect;int cnts=0,cntt=0;vi[k]=1;bool check=checkeft(cnts,cntt,vecs,vect,k);sort(vecs.begin(),vecs.end());sort(vect.begin(),vect.end());if(check) {rep(i,0,(int)vecs.size()-1) {if(vecs[i]!=vect[i]) {ans=0;break;}}}else{if((cnts&1)!=(cntt&1)) ans=0;rep(i,0,(int)vecs.size()-1) {if(vecs[i].fi!=vect[i].fi) {ans=0;break;}}}}if(ans) pf("YES\n");else pf("NO\n");rep(i,1,n) to[i].clear(),vi[i]=0;}
}

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

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

相关文章

个人知识面/技能池

虽然走得慢,但是一直在前行 知识面/技能池 电路 模拟电路微弱信号处理信号链设计1Msps采样电路设计滤波器设计无源滤波器有源滤波器光电探测电路设计电力电子逆变电路设计磁耦合谐振式无线电能传输开关电源LED恒流驱动AC/DC 设计基本电路知识电路基础知识复习跟习题册联系现代…

【CodeForces训练记录】Codeforces Round 977 (Div. 2, based on COMPFEST 16 - Final Round)

赛后反思 做红温了,太菜了,每题都需要WA几次才能过,B题看到 MEX 选择性害怕,时间复杂度又算错了 A题 每次选择一对 \(a_i,a_j\) 把均值插入数组最后面,要想结果最大,对于两个数求均值,最后的结果一定是小于等于其中的较大值,我们可以考虑如何最大化最后一次操作,想到将…

傻逼模拟赛搬的时候能不能看看题面改之后还是不是让人能看懂还有不发 checker 是有什么心事吗

如题。 傻逼模拟赛搬的时候能不能看看题面改之后还是不是让人能看懂还有不发 checker 是有什么心事吗还在最后一道题放集训队互测什么意思 什么叫有 \(b_{k}\) 种 \(k\) 类型的货币,同一种流通的货币不会超过二十种 什么叫接下来 \(n\) 个数表示 \(a_{1} \sim a_{n-1}\)upd:

Java - 10 二维数据

Java - 10 二维数据 一维数组的每个元素又是一个一维数组 静态初始化 int[][] arr = {{0,0,0,0},{1,1,1,1},{2,2,2,2},{3,3,3,3}};public class TwoDimensionArray {public static void main(String[] args) {int[][] arr = {{0,0,0,0},{1,1,1,1},{2,2,2,2},{3,3,3,3}};// 遍历…

Java - 11 类与对象

Java - 11 类与对象 类 类[属性, 行为] ->对象[属性, 行为] public class Test{public static void main(String[] args){Cat cat1 = new Cat(); // 创建对象cat1.name = "大宝";cat1.age = "3";cat1.color = "orange";System.out.println(ca…

20222413 2024-2025-1 《网络与系统攻防技术》实验一实验报告

1.实验内容 在本周的学习过程中,我了解到了许多缓冲区溢出攻击的实际案例、缓冲区溢出攻击的原理和相关基础知识,包括GDB调试器的使用方法、反汇编、基础的汇编语言与指令等,重新温习了函数调用过程和进程管理方面的知识内容。并且通过实验一,我能够了解并熟练完成Linux系统…

函数的上下文

函数的上下文 概述 在函数体的语句中,会出现this这个词,this就是函数的上下文 函数中this是谁,就说明函数的上下文是谁 函数中的this是谁,要看是如何调用的,因为this不是一成不变的 比如我们看下面的例子 var obj = {a: 100,fun: function() {console.log(this.a);} };我们…

拥挤聚集智能监测系统

拥挤聚集智能监测系统可以通过对人员数量、密度等进行实时监测,拥挤聚集智能监测系统识别出拥挤聚集的情况,并及时发出预警。拥挤聚集智能监测系统可以通过对人员进车间的人数等进行监测,识别出是否存在人员拥堵、挤压等安全隐患,及时发出警报,提醒工作人员采取措施疏散人…

睡岗识别 AI助力企业安全管控

睡岗识别可以通过AI视频智能分析技术,睡岗识别识别出操作人员是否存在睡岗情况。例如,在变电站等场景中,睡岗识别技术可以通过对识别出操作人员是否存在睡岗情况,及时发出预警,避免因操作人员的疏忽而导致的安全事故。在工厂车间中,睡岗识别技术可以通过对工人的行为进行…

加油站安全风险监测预警系统

加油站安全风险监测预警系统可以通过对加油站设备、环境、人员等方面进行监测,加油站安全风险监测预警系统实现对加油站的全面监管。例如,在加油站油罐区中,加油站安全风险监测预警系统可以对加油站人员抽烟打电话、明火烟雾等环境安全隐患进行自动识别,及时发出预警,避免…

山西煤矿电子封条

山西煤矿电子封条通过AI视觉分析技术,山西煤矿电子封条实现对各矿区(煤矿和非煤矿区)每日矿井出入井人监察控制、调度室空岗识别、煤矿生产作业状态、摄像头遮挡、挪动角度识别、货运车辆出矿识别等。山西煤矿电子封条实现当前待办事项的推送,以及对各矿区用户区域内的报警…

离岗识别 AI助力企业安全管控

离岗识别通过yolov5网络模型技术,离岗识别可以自动识别办公室、工厂、监控室监控画面中人员离岗脱岗睡岗等行为,发现违规行为立即抓拍告警并同步睡岗离岗等违规数据到后台提醒值班人员及时处理。离岗识别采用人工智能算法识别技术对各主控室、办公室、工厂、煤矿监控室等人员…