[luogu6185]序列

对于2操作,如果把这些操作看成边,那么对于某一个连通块内的若干个点,满足权值可以任意分配(证明:归纳,若n个点可以,那么先将新增的点调整好,再对原来n个点重新分配即可),因此可以将原图缩点,并将连通块的和作为新的权值
1操作比较复杂,同样把其当成边连起来,形成一张图(包括自环),然后考虑图中的一个连通块
对这张图,我们可以将操作复杂化:1.对一条长度为奇数的链,两端+1或-1;2.对一条长度为偶数的脸,两端一端+1,一端-1(转化的正确性容易证明)
如果不存在奇环,那么可以二分图染色,之后相当于左右各是一张2操作的完全图,左右之间点权差不变,即需要满足差值与目标差值相同即可
如果存在奇环,那么任意两点之间既存在一条奇数边,又存在一条偶数边,所以相当于既是2操作的完全图,又可以让总点权+2,那么只需要和与目标的和奇偶性相同即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 struct ji{
 5     int nex,to;
 6 }edge[N<<1];
 7 vector<int>v[3][N];
 8 int E,t,n,m,p,x,y,head[N],bl[N],a[N],b[N],sum[N];
 9 void add(int x,int y){
10     edge[E].nex=head[x];
11     edge[E].to=y;
12     head[x]=E++;
13 }
14 void dfs1(int k){
15     if (bl[k])return;
16     bl[k]=x;
17     sum[x]+=a[k]-b[k];
18     for(int i=0;i<v[2][k].size();i++)dfs1(v[2][k][i]);
19 }
20 bool dfs2(int k,int p){
21     if (bl[k]>=0)return bl[k]==p;
22     if (p)x+=sum[k];
23     else y+=sum[k];
24     bl[k]=p;
25     bool flag=1;
26     for(int i=head[k];i!=-1;i=edge[i].nex)flag&=dfs2(edge[i].to,p^1);
27     return flag;
28 }
29 int main(){
30     scanf("%d",&t);
31     while (t--){
32         scanf("%d%d",&n,&m);
33         E=0;
34         memset(bl,0,sizeof(bl));
35         memset(sum,0,sizeof(sum));
36         memset(head,-1,sizeof(head));
37         for(int i=1;i<=n;i++)v[1][i].clear();
38         for(int i=1;i<=n;i++)v[2][i].clear();
39         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
40         for(int i=1;i<=n;i++)scanf("%d",&b[i]);
41         for(int i=1;i<=m;i++){
42             scanf("%d%d%d",&p,&x,&y);
43             v[p][x].push_back(y);
44             v[p][y].push_back(x);
45         }
46         x=0;
47         for(int i=1;i<=n;i++)
48             if (!bl[i]){
49                 x++;
50                 dfs1(i);
51             }
52         for(int i=1;i<=n;i++)
53             for(int j=0;j<v[1][i].size();j++)add(bl[i],bl[v[1][i][j]]);
54         memset(bl,-1,sizeof(bl));
55         n=x;
56         bool flag=1;
57         for(int i=1;i<=n;i++)
58             if (bl[i]<0){
59                 x=y=0;
60                 p=dfs2(i,0);
61                 if (p)flag&=(x==y);
62                 else flag&=((x+y)%2==0);
63             }
64         if (flag)printf("YES
");
65         else printf("NO
");
66     }
67 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/12608269.html