codeforces 1250N wires(简单图论)

传送门

题意:给定n条边,连接编号从1到1e9之间的点,一次操作可以改变一条边连接的一个端点到另一个端点,也就是将第i条边(u,v)变成(u,w),v≠w,问最少次数操作使得这张图的所有边联通,输出操作次数k,以及每次操作的i,v,w。

分析:先将点离散化。假设有n个联通块s1,s2....sn,可以将连通块si内一条边端点改成si+1内一个点,但是改变这条边不能使得原有的连通块内的边变得不连通。dfs这个连通块最后一个被访问的边就是满足要求的边。

代码:

#include <bits/stdc++.h>
#define mp make_pair
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
typedef long long LL;
const int maxn = 4e5 + 10;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
typedef pair<int, int> p;
p e[maxn], tail[maxn];
int val[maxn], len = 0, n, t, ord[maxn], vis[maxn], tot = 0, head[maxn], to[maxn], tots;
vector<int> g[maxn];
void dfs(int x, int pre) {
    vis[x] = true;
    for (int i = 0; i < g[x].size(); ++i) {
        int v = to[g[x][i]];
        if (!vis[v]) {
            tail[tot] = mp(g[x][i] / 2 + 1, v);
            dfs(v, x);
        }
    }
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> t;
    while (t--) {
        cin >> n;
        len = 0;
        tot = 0;
        tots = 0;
        for (int i = 0; i < n; ++i) {
            cin >> e[i].first >> e[i].second;
            val[len++] = e[i].first;
            val[len++] = e[i].second;
        }
        sort(val, val + len);
        len = unique(val, val + len) - val;
        for (int i = 0; i < len; ++i) {
            vis[i] = 0;
            g[i].clear();
        }
        for (int i = 0; i < n; ++i) {
            int fu = lower_bound(val, val + len, e[i].first) - val;
            ord[fu] = e[i].first;
            e[i].first = fu;
            fu = lower_bound(val, val + len, e[i].second) - val;
            ord[fu] = e[i].second;
            e[i].second = fu;
            to[tots] = e[i].second;
            g[e[i].first].pb(tots++);
            to[tots] = e[i].first;
            g[e[i].second].pb(tots++);
        }
        /*for (int i = 0; i < tots; ++i)
            cout << to[i] << endl;*/
        for (int i = 0; i < len; ++i) {
            if (!vis[i]) {
                ++tot;
                head[tot] = i;
                dfs(i, -1);
            }
        }
        cout << tot - 1 << "\n";
        for (int i = 1; i < tot; ++i) {
            cout << tail[i].first  << " " << ord[tail[i].second] << " " << ord[head[i + 1]] << "\n";
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/smallhester/p/11774296.html