zoukankan      html  css  js  c++  java
  • [欧拉回路][并查集] Bzoj P3706 反色刷

    Description

    给一张无向图,边有黑白两种颜色,现在你有一堆反色刷,可以从任意点开始刷,经过若干条边后回到起点。
    现在要询问至少需要多少个反色刷可以使这张图所有边都变成白色。
    因为某种原因,边的颜色是会改变的,于是。。
    需要支持以下操作:
    1 x  把第x条边反色(编号从0~m-1)
    2   询问当前图中最少需要多少个反色刷

    Input

    第一行两个整数n m表示这张图有n个点m条边
    接下来m行 每行3个整数 u v c表示一条无向边和这条边的颜色(0为白色 1为黑色)
    接下来一个整数q 表示有q个操作
    接下来q行为操作 描述如上

    Output

    对于每个询问 输出一行一个整数
    表示最少需要的反色刷个数 如果没有合法方案输出-1

    Sample Input

    6 6
    1 2 1
    2 3 1
    1 3 1
    4 5 1
    5 6 1
    4 6 1
    14
    2
    1 0
    2
    1 1
    1 2
    2
    1 3
    1 4
    1 5
    2
    1 3
    1 4
    1 5
    2

    Sample Output

    2
    -1
    1
    0
    1

    Hint

    100%  n,m,q <= 1000000, c < 2,没有重边自环

    题解

    • 首先题目有解当且仅当每个点连接的黑边数量均为偶数
    • 若有解答案就等于存在黑边的连通块数量
    • 证明:对于一个连通块,假设当前选择了两条分别从u和v开始的不相交的路径
    • 我们可以通过先走u为起点的路径,然后从u走到v,再走从v开始的路径
    • 最后回到u来将这两条路径合并

    代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 const int N=1000005;
     6 int n,m,cnt,now,q,f[N],d[N],col[N];
     7 struct edge{int x,y,c;}e[N];
     8 int find(int x) { return f[x]==x?x:f[x]=find(f[x]); }
     9 int main()
    10 {
    11     scanf("%d%d",&n,&m);
    12     for (int i=1;i<=n;i++) f[i]=i;
    13     for (int i=1,x,y,z;i<=m;i++)
    14     {
    15         scanf("%d%d%d",&x,&y,&z),e[i].x=x,e[i].y=y,e[i].c=z;
    16         if (z) now-=d[x]+d[y],d[x]^=1,d[y]^=1,now+=d[x]+d[y];
    17         if (find(x)!=find(y)) f[find(x)]=find(y);
    18     }
    19     for (int i=1;i<=m;i++)
    20         if (e[i].c)
    21         {
    22             int x=find(e[i].x);
    23             if (!col[x]) cnt++;
    24             col[x]++;
    25         }
    26     scanf("%d",&q);
    27     for (int op,x;q;q--)
    28     {
    29         scanf("%d",&op);
    30         if (op==2) printf("%d
    ",now?-1:cnt);
    31         else
    32         {
    33             scanf("%d",&x),x++;
    34             now-=d[e[x].x]+d[e[x].y],d[e[x].x]^=1;d[e[x].y]^=1,now+=d[e[x].x]+d[e[x].y];
    35             if (e[x].c)
    36             {
    37                 e[x].c=0,col[find(e[x].x)]--;
    38                 if (!col[find(e[x].x)]) cnt--;
    39             }
    40             else
    41             {
    42                 e[x].c=1;
    43                 if (!col[find(e[x].x)]) cnt++;
    44                 col[find(e[x].x)]++;
    45             }
    46         }
    47     }
    48     return 0;
    49 } 
  • 相关阅读:
    SWT DragSource 和 DropTarget 托拉拽
    Java的反射机制
    1. 算法导论
    SWT对于监听Tab键的理解
    SWT基础
    socket
    TCP/IP
    RPC(远程过程调用协议)
    Jython基本知识
    #与##
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11145176.html
Copyright © 2011-2022 走看看