BZOJ 1015 星球大战starwar 逆向并查集
题目链接:
https://www.lydsy.com/JudgeOnline/problem.php?id=1015
题目大意:
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)
思路:
删点之后不好维护,所以离线下来,逆向处理,逐渐加点维护连通块个数即可。
1 #include<bits/stdc++.h> 2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf 3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时 4 #define Min(a, b) ((a) < (b) ? (a) : (b)) 5 #define Mem(a) memset(a, 0, sizeof(a)) 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1)) 7 #define MID(l, r) ((l) + ((r) - (l)) / 2) 8 #define lson ((o)<<1) 9 #define rson ((o)<<1|1) 10 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 16 while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 typedef long long ll; 20 const int maxn = 400000 + 10; 21 const int mod = 100003;//const引用更快,宏定义也更快 22 const int INF = 1e9; 23 int p[maxn]; 24 vector<int>G[maxn]; 25 bool vis[maxn]; 26 stack<int>ans; 27 int Find(int x) 28 { 29 return x == p[x] ? x : p[x] = Find(p[x]); 30 } 31 int a[maxn]; 32 int main() 33 { 34 int n, m, u, v; 35 scanf("%d%d", &n, &m); 36 while(m--) 37 { 38 scanf("%d%d", &u, &v); 39 G[u].push_back(v); 40 G[v].push_back(u); 41 } 42 for(int i = 0; i < n; i++)p[i] = i; 43 scanf("%d", &m); 44 for(int i = 0; i < m; i++)scanf("%d", &a[i]), vis[a[i]] = 1; 45 for(int u = 0; u < n; u++) 46 { 47 if(!vis[u])for(int i = 0; i < G[u].size(); i++) 48 { 49 int v = G[u][i]; 50 if(!vis[v]) 51 { 52 int x = Find(u), y = Find(v); 53 p[x] = y; 54 } 55 } 56 } 57 int tot = 0; 58 for(int i = 0; i < n; i++)if(!vis[i])if(p[i] == i)tot++; 59 ans.push(tot); 60 for(int i = m - 1; i >= 0; i--) 61 { 62 int u = a[i], cnt = 0; 63 vis[u] = 0; 64 for(int j = 0; j < G[u].size(); j++) 65 { 66 int v = G[u][j]; 67 if(!vis[v]) 68 { 69 int x = Find(u), y = Find(v); 70 if(x != y) 71 { 72 cnt++; 73 p[x] = y; 74 } 75 } 76 } 77 tot = tot - cnt + 1; 78 ans.push(tot); 79 } 80 while(!ans.empty()) 81 { 82 printf("%d\n", ans.top()), ans.pop(); 83 } 84 return 0; 85 }
越努力,越幸运