[cf1537F] Figure Fixing

由于每次同时给两个点加k,所以若初始v[i]的和与t[i]的和奇偶性不同则一定不能。

然后考虑如果是二分图。好像对于图论题,这种看不出什么的时候经常会考虑:如果是二分图则balabala...二分图总有些优秀的性质叭。那么把点黑白染色一下,每条边连接一黑一白,也就是说每次修改点值会分别给一个黑点一个白点加上k。那么初始情况下,黑点v[i]-c[i]之和与白点v[i]-c[i]之和必须相同才有可能行。又因为图的连通性,所以两边只要相同就一定可以都变成0。

在此基础上考虑不是二分图的情况,也就可以转化为比一个二分图多了黑点内部的边或白点内部的边,那显然一定可以了,因为可以通过该边把两边v[i]-c[i]的和调到相同。再加上之前的推理,就能得到结论。

关于如何判断是否是二分图:做bfs,把当前搜到的点所有相邻点都染成和它不同的颜色,如果此前已经染过相同颜色了,则不是二分图,反之则是。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
const int N=200010;
struct edge{
	int y,next;
}data1[N*2];
bool flag,vis[N];
int t,n,m,num,h[N],v1[N],t1[N],col[N];
ll sumv,sumt;
queue<int> q;
inline int read(){
	int x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return f?-x:x; 
}
inline void addedge(int u,int v){
	data1[++num].y=v,data1[num].next=h[u],h[u]=num;
	data1[++num].y=u,data1[num].next=h[v],h[v]=num;
}
int main(){
	t=read();
	while(t--){
		n=read(),m=read();
		sumv=sumt=0;
		for(int i=1;i<=n;++i){v1[i]=read();sumv+=1ll*v1[i];}
		for(int i=1;i<=n;++i){t1[i]=read();sumt+=1ll*t1[i];}
		for(int i=1;i<=n;++i)col[i]=-1,h[i]=-1,vis[i]=false;
		num=0;
		for(int i=1,u,v;i<=m;++i){
			u=read(),v=read();
			addedge(u,v);
		}
		if(abs(sumv-sumt)&1){printf("NO\n");continue;}
		while(!q.empty())q.pop();
		q.push(1);col[1]=0;flag=true;
		while(!q.empty()){
			int u=q.front();q.pop();
			vis[u]=true;
			for(int i=h[u],v;i!=-1;i=data1[i].next){
				v=data1[i].y;
				if(vis[v])continue;
				if(col[v]==col[u]){flag=false;break;}
				else if(col[v]==-1){col[v]=1-col[u];q.push(v);}
			}
			if(!flag)break;
		}
		if(!flag)printf("YES\n");
		else{
			sumv=sumt=0;
			for(int i=1;i<=n;++i){
				if(col[i])sumt+=1ll*v1[i]-t1[i];
				else sumv+=1ll*v1[i]-t1[i];
			}
			if(sumv==sumt)printf("YES\n");
			else printf("NO\n");
		}
	}
	return 0;
} 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值