NC212821小y的旅行

    科技2022-08-01  114

    题意: 给定 n n n m m m条无向边,最少需要删除多少条边可以使得所有编号 ≤ k \leq k k的点都不在环上。 数据范围: 1 ≤ n ≤ 1 0 6 , 1 ≤ m ≤ 2 × 1 0 6 , 1 ≤ k ≤ n 1\leq n\leq 10^6, 1\leq m\leq 2\times 10^6, 1\leq k\leq n 1n106,1m2×106,1kn

    题解: 构造生成树。

    先用所有编号大于 k k k的点连成的边构造生成树。然后用所有存在编号 ≤ k \leq k k的边来构造生成树。当无法加入时,说明该边需删除,否则该边加入生成树即可。

    代码:

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> #include<stack> #include<queue> #include<map> #include<vector> #include<cmath> using namespace std; typedef long long ll; template<typename T> inline T Read(){ T s = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - '0'; ch = getchar();} return s * f; } #define read() Read<int>() #define readl() Read<long long>() const int N = 1e6 + 10, M = 2e6 + 10; int p[N]; struct Node{ int a, b; bool operator < (const Node &A) const { return a > A.a; } }e[M]; int find(int x) { if(x != p[x]) p[x] = find(p[x]); return p[x]; } void solve() { int n = read(), m = read(), k = read(); int res = 0; for(int i = 1; i <= n; i++) p[i] = i; for(int i = 1; i <= m; i++) { int a = read(), b = read(); if(a > b) swap(a, b); e[i] = {a, b}; } sort(e + 1, e + m + 1); for(int i = 1; i <= m; i++) { int a = e[i].a, b = e[i].b; int fa = find(a), fb = find(b); if(fa != fb) p[fa] = fb; else if(a <= k) ++res; } printf("%d\n", res); } int main() { int T = 1; //T = read(); for(int i = 1; i <= T; ++i) { solve(); } return 0; }
    Processed: 0.010, SQL: 8