其他分享
首页 > 其他分享> > luogu P6185 [NOI Online 提高组]序列 并查集缩点 二分图

luogu P6185 [NOI Online 提高组]序列 并查集缩点 二分图

作者:互联网

首先现在操作2,一个+1,一个-1。就好比权值可以在两点之间流动。我们发现,把操作2当作边,则一个联同的子图,内部的权值是可以随便流动的。我们就这个把这个子图看多一个点。这个我们用并查集来实现。那么这个并查集内的s[i]也对应求和。

我们把操作2,都处理完了,我们再考虑操作2。对于操作1,我们连边,注意此时的点已经缩小过。我们可以发现,如果一个联同子图,是二分图,则可以作到,两个部分在差不变的情况下,变成任意值。就是如果两个部分的s[i]的和相同,减去同样的差,变为0,则可以。如果一个联通子图,不是二分图,那么我们可以作到,总的奇偶性不变下,任意加减。就是如果总的s[i]的和为偶数,则可以变为0,则可行。

这题判断奇偶可能有负数,闲的写了个%2==1,找了2个小时.....

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 using namespace std;
  5 typedef long long ll;
  6 ll s[210000],sum[3];
  7 int n,m,ans,T,a[210000],b[210000],fa[210000],siz[210000],qry[210000][2],col[210000];
  8 int ecnt,cnt,head[210000],nxt[420000],to[420000];
  9 void add(int x,int y)
 10 {
 11     nxt[++ecnt] = head[x];
 12     to[ecnt] = y;
 13     head[x] = ecnt;
 14 }
 15 int getfa(int x)
 16 {
 17     if (fa[x] == x)
 18         return x;
 19     return fa[x] = getfa(fa[x]);
 20 }
 21 void merge(int x,int y)
 22 {
 23     int s1 = getfa(x),s2 = getfa(y);
 24     if (s1 == s2)
 25         return;
 26     if (siz[s1] < siz[s2])
 27     {
 28         fa[s1] = s2;
 29         siz[s2] += siz[s1];
 30     }else
 31     {
 32         fa[s2] = s1;
 33         siz[s1] += siz[s2];
 34     }
 35 }
 36 bool dfs(int x,int k)
 37 {
 38     col[x] = k;
 39     sum[k] += s[x];
 40     bool suc = true;
 41     for (int i = head[x];i;i = nxt[i])
 42     {
 43         if (col[to[i]] == col[x])
 44             suc = false;
 45         if (col[to[i]] == 0 && dfs(to[i],3 - k) == false)
 46             suc = false;
 47     }
 48     return suc;
 49 }
 50 int main()
 51 {
 52     for (scanf("%d",&T);T;T--)
 53     {
 54         for (int i = 1;i <= ecnt;i++)
 55             nxt[i] = 0;
 56         cnt = ecnt = 0;
 57         ans = 1;
 58         scanf("%d%d",&n,&m);
 59         for (int i = 1;i <= n;i++)
 60             s[i] = col[i] = head[i] = 0;
 61         for (int i = 1;i <= n;i++)
 62             scanf("%d",&a[i]);
 63         for (int i = 1;i <= n;i++)
 64             scanf("%d",&b[i]);
 65         for (int i = 1;i <= n;i++)
 66             fa[i] = i,siz[i] = 1;
 67         int topt,tx,ty;
 68         for (int i = 1;i <= m;i++)
 69         {
 70             scanf("%d%d%d",&topt,&tx,&ty);
 71             if (topt == 2)
 72                 merge(tx,ty);
 73             else
 74             {
 75                 qry[++cnt][0] = tx;
 76                 qry[cnt][1] = ty;
 77             }
 78         }
 79         for (int i = 1;i <= n;i++)
 80             s[getfa(i)] += b[i] - a[i];
 81         for (int i = 1;i <= cnt;i++)
 82         {
 83             add(getfa(qry[i][0]),getfa(qry[i][1]));
 84             add(getfa(qry[i][1]),getfa(qry[i][0])); 
 85         }
 86         for (int i = 1;i <= n;i++)
 87         {
 88             if (getfa(i) != i || col[i])
 89                 continue;
 90             sum[1] = sum[2] = 0;
 91             bool suc = dfs(i,1);
 92             if (suc && sum[1] != sum[2])
 93             {
 94                 ans = 0;
 95                 break;
 96             }
 97             if (!suc && ((sum[1] + sum[2]) & 1))
 98             {
 99                 ans = 0;
100                 break;
101             }
102         }
103         printf("%s\n",ans ? "YES" : "NO"); 
104     }
105 }

 

标签:s2,P6185,NOI,fa,int,luogu,s1,210000,siz
来源: https://www.cnblogs.com/iat14/p/12495257.html