1. 程式人生 > >ZOJ-3261 Connections in Galaxy War---離線操作+逆序並查集

ZOJ-3261 Connections in Galaxy War---離線操作+逆序並查集

destroy else har 離線操作 ron cti 操作 gin 無連接

題目鏈接:

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("\n"); 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\n", ans[i]); 99 } 100 return 0; 101 }

ZOJ-3261 Connections in Galaxy War---離線操作+逆序並查集