zoukankan      html  css  js  c++  java
  • HDU_3038 How Many Answers Are Wrong 【带权并查集】

    一、题面

    HDU3038

    二、分析

    用并查集可以方便的判断两个位置是否有关系,这种关系可以通过是否有公共父节点判断,如果有公共父节点则可以直接判断是否正确,如果没有公共父节点,就可以把这个条件与之前的联系起来。同时需要设定sum,表示当前点到父节点的权值,这个权值方便后面的判断,这里有几种情况。

    假设输入为$(x,y,w)$,那么对应父节点$fx = find(x), fy = find(y)$:

    1.如果$fx==fy$:那么可以直接判断$w == sum[x] - sum[y]$.

    2.如果$ x < y < fx < fy$:这里需要更新并查集的信息,$par[fx] = fy, sum[fx] = sum[y] - (sum[x] - w)$.

    3.如果$ x < fx < y < fy$:此时,$par[fx] = fy, sum[fx] = sum[y] + (w - sum[x])$.

    4.如果$ x < y < fy < fx$:此时,$par[fy] = fx, sum[fy] = sum[x] - sum[y] - w$.

    分析上面四种情况,可以得出2和3可以合并,对于4,仔细分析一下, 相当于就是3的情况,只是因为$par[fy] = fx$,只是这样可以保证$sum$的值为正。注意在路径压缩时,对$sum$进行更新就可以了。

    细心的朋友可能发现了,还有$x = y$的情况呢。对于这种情况,我们可以直接对输入的左值整体再往左移一下,就是输入的$u$变成$u-1$,这个对结果是没有影响的。但是如果不减,我们就要考虑$x=y$的情况了,前面我们已经初始化了$sum$初值为0,并且$x=y$的左右两边的情况我们是不能保证完全清楚的。所以这样把$x=y$变成了$(x-1,y]$这个区间的形式,就让问题又归到了我们上面讨论的情况,更简单了。

    三、AC代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <fstream>
     5 #include <map>
     6 
     7 using namespace std;
     8 
     9 const int MAXN = 2e5+3;
    10 int par[MAXN];
    11 int sum[MAXN];
    12 
    13 void Init()
    14 {
    15     for(int i = 0; i < MAXN; i++)
    16         par[i] = i;
    17     memset(sum, 0, sizeof(sum));
    18 }
    19 
    20 int Find(int x)
    21 {
    22     if(par[x] == x)
    23         return x;
    24     int fx = par[x];
    25     par[x] = Find(fx);
    26     sum[x] = sum[fx] + sum[x];
    27     return par[x];
    28 }
    29 
    30 bool Union(int x, int y, int w)
    31 {
    32     int fx = Find(x);
    33     int fy = Find(y);
    34     // if(fx != fy)
    35     // {
    36     //     par[fx] = fy;
    37     //     sum[fx] = w + sum[y] - sum[x];
    38     //     return true;
    39     // }
    40     // else
    41     // {
    42     //     return w == sum[x] - sum[y];
    43     // }
    44     if(fx < fy)
    45     {
    46         par[fx] = fy;
    47         sum[fx] = w + sum[y] - sum[x];
    48         return true;
    49     }
    50     else if(fx > fy)
    51     {
    52         par[fy] = fx;
    53         sum[fy] = sum[x] - w - sum[y];
    54         return true;
    55     }
    56     else
    57     {
    58         return w == sum[x] - sum[y];
    59     }
    60 
    61 }
    62 
    63 int main()
    64 {
    65    // freopen("input.txt", "r", stdin);
    66     int N, M;
    67     while(scanf("%d %d", &N, &M)!=EOF)
    68     {
    69         Init();
    70         int a, b, w, ans = 0;
    71         for(int i = 0; i < M; i++)
    72         {
    73             scanf("%d %d %d", &a, &b, &w);
    74             if(!Union(a-1, b, w))
    75                 ans++;
    76         }
    77         printf("%d
    ", ans);
    78     }
    79     return 0;
    80 }
    View Code
  • 相关阅读:
    “XXXXX” is damaged and can’t be opened. You should move it to the Trash 解决方案
    深入浅出 eBPF 安全项目 Tracee
    Unity3d开发的知名大型游戏案例
    Unity 3D 拥有强大的编辑界面
    Unity 3D物理引擎详解
    Unity 3D图形用户界面及常用控件
    Unity 3D的视图与相应的基础操作方法
    Unity Technologies 公司开发的三维游戏制作引擎——Unity 3D
    重学计算机
    windows cmd用户操作,添加,设备管理员组,允许修改密码
  • 原文地址:https://www.cnblogs.com/dybala21/p/10138765.html
Copyright © 2011-2022 走看看