1 条题解
-
1
正向删点删边太麻烦了怎么办?那就反向加边嘛!
把每个团伙当作点,能联络就代表两者间有边相连,该点蔓延的连通块大小的就是危险程度。
先用vector将边存储。再反向遍历n -> k 并加边 直至当前点(k)加边后的连通块大小大于等于n/2,输出k
#include <bits/stdc++.h> #define int long long int using namespace std; const int N = 2e5 + 7; int n,m; int fa[N << 1],tot[N]; vector<int> e[N]; inline int read(){ int x = 0,f = 1; char c = getchar(); for(;!isdigit(c);c = getchar()) if(c == '-')f = -1; for(;isdigit(c);c = getchar()) x = (x << 1) + (x << 3) + c - '0'; return x * f; } int get(int x){ if(fa[x] == x)return x; return fa[x] = get(fa[x]); } void merge(int x,int y){ x = get(x); y = get(y); if(x != y){//注意判是否已经为一家,防止累加 fa[x] = y; tot[y] += tot[x]; } } void print(int x,int y){ if(get(x) == get(y)) printf("Y\n"); else printf("N\n"); } signed main(){ n = read(); for(int i = 1;i <= n;i ++){ fa[i] = i; tot[i] = 1; } for(int i = 1;i <= n;i ++){ int k = read(); while(k --){ int j = read(); e[i].push_back(j); } } for(int i = n;i > 0;i --){ for(int j = 0;j < e[i].size();j ++) if(e[i][j] > i) merge(e[i][j],i); if(tot[get(i)] > (n / 2)){ printf("%lld",i); return 0; } } return 0; }
- 1
信息
- ID
- 396
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 2
- 上传者