【JSOI2008】星球大战
本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1197
也不算太难吧,正着想先建图再拆点不太好实现,不如先把所有数据读入,然后倒着添加点。
然后就是对代码能力和人品的考验了,,,一个小做法考虑的不好就导致只有10分。。。
1 #include <cstdio> 2 3 inline int get_num() { 4 int num = 0; 5 char c = getchar(); 6 while (c < '0' || c > '9') c = getchar(); 7 while (c >= '0' && c <= '9') 8 num = num * 10 + c - '0', c = getchar(); 9 return num; 10 } 11 12 const int maxn = 4e5 + 5, maxm = 2e5 + 5; 13 14 int fa[maxn], head[maxn], eid; 15 16 struct Edge { 17 int u, v, next; 18 } edge[2 * maxm]; 19 20 inline void insert(int u, int v) { 21 edge[++eid].u = u; 22 edge[eid].v = v; 23 edge[eid].next = head[u]; 24 head[u] = eid; 25 } 26 27 int dj_find(int i) { 28 if (i == fa[i]) return i; 29 else return fa[i] = dj_find(fa[i]); 30 } 31 32 inline void dj_merge(int a, int b) { 33 a = dj_find(a), b = dj_find(b); 34 if (a != b) fa[a] = b; 35 } 36 37 int vis[maxn], del[maxn], out[maxn]; 38 39 int main() { 40 int n, m, x, y, k, ans; 41 n = get_num(), m = get_num(); 42 for (int i = 1; i <= m; ++i) { 43 x = get_num(), y = get_num(); 44 insert(x, y); 45 insert(y, x); 46 } 47 k = get_num(); 48 for (int i = 1; i <= k; ++i) 49 vis[del[i] = get_num()] = 1; 50 for (int i = 0; i < n; ++i) fa[i] = i; 51 ans = n - k; 52 for (int i = 0; i < n; ++i) { 53 if (vis[i]) continue; 54 for (int j = head[i]; j; j = edge[j].next) { 55 int u = edge[j].u, v = edge[j].v; 56 if (vis[v]) continue; 57 if (dj_find(u) != dj_find(v)) { 58 dj_merge(u, v); 59 --ans; 60 } 61 } 62 } 63 out[k] = ans; 64 for (int i = k; i >= 1; --i) { 65 int u = del[i]; 66 vis[u] = 0, ++ans; 67 for (int j = head[u]; j; j = edge[j].next) { 68 int v = edge[j].v; 69 if (vis[v]) continue; 70 if (dj_find(u) != dj_find(v)) { 71 dj_merge(u, v); 72 --ans; 73 } 74 } 75 out[i - 1] = ans; 76 } 77 for (int i = 0; i <= k; ++i) printf("%d\n", out[i]); 78 return 0; 79 }