zoukankan      html  css  js  c++  java
  • ZOJ-3261 Connections in Galaxy War---离线操作+逆序并查集

    题目链接:

    https://cn.vjudge.net/problem/ZOJ-3261

    题目大意:

    给你一些点,还有一些边,每个点上都有一个权值,然后有一些询问,分为两种,
    query a 询问与a直接或者间接想连的点中最大权值的是那个点,输出那个点,如果那个点的权值小于等于a的权值,那么就输出-1,还有另一种操作就是destroy a b意思是删除a b的关系。

    解题思路:

    此处需要删边,应该想到逆序离线处理。先将所有需要删除的边直接删除,将所有操作存下来逆序处理,对于需要删的边就变成添加这条边。求与a相连的权值最大的点,就直接求a这个连通块中的最大权值的点,可以用并查集求,添加边的时候就合并两个连通块即可。

    注意合并连通块时,权值大的为父亲,如果权值相同,那么编号小的为父亲

    在最后判断是否存在为-1的时候,需要用连通块根节点的权值和当前询问节点权值进行比较,不可用下标相等比较

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int maxn = 1e5 + 10;
      5 int n, m;
      6 int a[maxn];//每个点的权值
      7 vector<int>Map[maxn];//存边(只保留编号小的指向编号大的边)
      8 struct node//存储操作
      9 {
     10     int type, x, y;
     11 }op[maxn];
     12 vector<int>ans;
     13 int fa[maxn];
     14 int Find(int x)
     15 {
     16     return x == fa[x] ? x : fa[x] = Find(fa[x]);
     17 }
     18 void Union(int x, int y)
     19 {
     20     x = Find(x), y = Find(y);
     21     if(a[x] < a[y])
     22     {
     23         fa[x] = y;
     24     }
     25     else if(a[x] > a[y])
     26     {
     27         fa[y] = x;
     28     }
     29     else if(x != y)
     30     {
     31         if(x < y)
     32         {
     33             fa[y] = x;
     34         }
     35         else
     36         {
     37             fa[x] = y;
     38         }
     39     }
     40 }
     41 int main()
     42 {
     43     int flag = 0;
     44     while(scanf("%d", &n) != EOF)
     45     {
     46         if(flag++)printf("
    ");
     47         memset(op, 0, sizeof(op));
     48         memset(a, 0, sizeof(a));
     49         ans.clear();
     50         for(int i = 0; i < n; i++)scanf("%d", &a[i]), Map[i].clear(), fa[i] = i;
     51 
     52         scanf("%d", &m);
     53         int u, v;
     54         while(m--)
     55         {
     56             scanf("%d%d", &u, &v);
     57             if(u > v)swap(u, v);
     58             Map[u].push_back(v);
     59         }
     60         scanf("%d", &m);
     61         char s[10];
     62         for(int i = 1; i <= m; i++)
     63         {
     64             scanf("%s", s);
     65             if(s[0] == 'q')
     66                 op[i].type = 1, scanf("%d", &op[i].x);
     67             else //先将边全部删除,逆序操作,逐渐增加边
     68             {
     69                 op[i].type = 2;
     70                 scanf("%d%d", &u, &v);
     71                 if(u > v)swap(u, v);
     72                 op[i].x = u, op[i].y = v;
     73                 Map[u].erase(find(Map[u].begin(), Map[u].end(), v));
     74             }
     75         }
     76         for(int i = 0; i < n; i++)
     77         {
     78             for(int j = 0; j < Map[i].size(); j++)
     79             {
     80                 Union(i, Map[i][j]);
     81             }
     82         }
     83         for(int i = m; i >= 1; i--)
     84         {
     85             if(op[i].type == 1)
     86             {
     87                 u = Find(op[i].x);
     88                 if(a[u] <= a[op[i].x])u = -1;
     89                 //不能仅仅判断u != op[i].x 因为根节点可能为其他点并且权值等于该节点权值,此时该节点也应该认为无连接
     90                 ans.push_back(u);
     91             }
     92             else
     93             {
     94                 Union(op[i].x, op[i].y);
     95             }
     96         }
     97         for(int i = ans.size() - 1; i >= 0; i--)
     98             printf("%d
    ", ans[i]);
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    selector 使用说明
    volley用法之 以post方式发送 json 参数
    linux系统下使用流行的版本管理工具 Git
    Android BLE 蓝牙编程(四)
    Android BLE 蓝牙编程(三)
    Android BLE 蓝牙编程(二)
    Android BLE 蓝牙编程(一)
    php比较两个字符串是否相同
    下拉刷新
    理财小工具(二)贷款计算器
  • 原文地址:https://www.cnblogs.com/fzl194/p/9320665.html
Copyright © 2011-2022 走看看