• [PTA]L2-013 红色警报


    粗略看了一下网上其他题解,都是暴力跑的,也就是对于每个询问重建并查集,这样其实时间复杂度是$O(n^2logn)$的,十分不优秀。

    其实有更好的解法,就是时间倒流法,倒序处理每个询问,每个把删去一个点删边改成加上一个点加边,一遍并查集即可。 

    每次判断是否合并了两个以上的连通块。

    注意一条边可用当且仅当两端的点都存在。

     1 #include <bits/stdc++.h>
     2 #define Mid ((l + r) >> 1)
     3 #define lson (rt << 1)
     4 #define rson (rt << 1 | 1)
     5 using namespace std;
     6 int read(){
     7     char c; int num, f = 1;
     8     while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
     9     while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    10     return f * num;
    11 }
    12 const int N = 509;
    13 int n, m, pre[N], a[N], f[N], vis[N];
    14 vector<int> ver[N];
    15 int fid(int x) {
    16     return pre[x] == x ? x : (pre[x] = fid(pre[x]));
    17 }
    18 signed main()
    19 {
    20     n = read(); m = read();
    21     for(int i = 1; i <= m; i++) {
    22         int x = read() + 1, y = read() + 1;
    23         ver[x].push_back(y);
    24         ver[y].push_back(x);
    25     }
    26     for(int i = 1; i <= n; i++) pre[i] = i;
    27     int q = read();
    28     for(int i = 1; i <= n; i++) vis[i] = 1;
    29     for(int i = 1; i <= q; i++) vis[a[i] = read() + 1] = 0;
    30     for(int x = 1; x <= n; x++) if(vis[x])
    31         for(auto j : ver[x]) 
    32             if(vis[j] && fid(j) != fid(x)) 
    33                 pre[fid(j)] = fid(x);
    34     for(int i = q; i; i--) {
    35         int ff = 0;
    36         for(auto j : ver[a[i]]) {
    37             if(vis[j] && fid(j) != fid(a[i])) {
    38                 pre[fid(j)] = fid(a[i]);
    39                 ff++;
    40             }
    41         }
    42         vis[a[i]] = 1;
    43         if(ff > 1) f[i] = 1;
    44     }
    45     for(int i = 1; i <= q; i++) {
    46         if(f[i]) printf("Red Alert: City %d is lost!
    ", a[i] - 1);
    47         else printf("City %d is lost.
    ", a[i] - 1);
    48     }
    49     if(q == n) {
    50         printf("Game Over.
    ");
    51     }
    52     return 0;
    53 }
    View Code
  • 相关阅读:
    多播委托和匿名方法再加上Lambda表达式
    委托
    从警察抓小偷看委托
    StringBuilder
    C#修饰符详解
    数据结构与算法之队列
    数据结构与算法之栈
    win10重复安装
    网络编程基础
    PrintPreviewControl
  • 原文地址:https://www.cnblogs.com/onglublog/p/14309277.html
Copyright © 2020-2023  润新知