标签:问题 type ret href dig pac print 链接 color
[题目链接]
http://codeforces.com/problemset/problem/1037/E
[算法]
首先离线 , 将问题倒过来考虑 , 转化为 : 每次删除一条边 , 此时最多有多少人参加旅行
假设所有点都选取 , 那么 ,如果一个点的度数 < k , 显然这个点不能选 , 我们需要删除它和所有与它相邻的边
显然 , 所有的点和边最多只会被删去一次 , 故时间复杂度为O(N + M)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 10; int n , m , k; int deg[MAXN],res[MAXN],x[MAXN],y[MAXN],q[MAXN]; bool visited[MAXN],del[MAXN]; vector< int > a[MAXN],b[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘; x *= f; } int main() { read(n); read(m); read(k); for (int i = 1; i <= m; i++) { read(x[i]); read(y[i]); a[x[i]].push_back(y[i]); a[y[i]].push_back(x[i]); b[x[i]].push_back(i); b[y[i]].push_back(i); deg[x[i]]++; deg[y[i]]++; } int l = 1 , r = 0 ,ans = n; for (int i = 1; i <= n; i++) { if (deg[i] < k) { visited[i] = true; q[++r] = i; ans--; } } for (int i = m; i >= 1; i--) { while (l <= r) { int u = q[l++]; for (unsigned j = 0; j < a[u].size(); j++) { if (!del[b[u][j]]) { deg[u]--; deg[a[u][j]]--; del[b[u][j]] = true; if (!visited[a[u][j]] && deg[a[u][j]] < k) { ans--; visited[a[u][j]] = true; q[++r] = a[u][j]; } } } } res[i] = ans; if (!del[i]) { del[i] = true; deg[x[i]]--; deg[y[i]]--; if (!visited[x[i]] && deg[x[i]] < k) { visited[x[i]] = true; ans--; q[++r] = x[i]; } if (!visited[y[i]] && deg[y[i]] < k) { visited[y[i]] = true; ans--; q[++r] = y[i]; } } } for (int i = 1; i <= m; i++) printf("%d\n",res[i]); return 0; }
标签:问题 type ret href dig pac print 链接 color
原文地址:https://www.cnblogs.com/evenbao/p/9737353.html