Submission #62556783


Source Code Expand

Copy
#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for (int i=0;i<(n);i++)
#define ALL(obj) begin(obj), end(obj)
typedef long long ll;
typedef pair<int,int> pii;
struct UnionFind {
vector<int> par, rank, siz;
UnionFind(int n) : par(n,-1), rank(n,0), siz(n,1) { }
int root(int x) {
if(par[x] == -1) return x;
return par[x] = root(par[x]);
}
bool unite(int x, int y) {
int rx = root(x), ry = root(y);
if(rx==ry)return false;
if(rank[rx]<rank[ry]) swap(rx,ry);
par[ry]=rx;
if(rank[rx]==rank[ry]) rank[rx]++;
siz[rx]+=siz[ry];
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for (int i=0;i<(n);i++)
#define ALL(obj) begin(obj), end(obj)
typedef long long ll;
typedef pair<int,int> pii;

struct UnionFind {
    vector<int> par, rank, siz;
    UnionFind(int n) : par(n,-1), rank(n,0), siz(n,1) { }
    int root(int x) {
        if(par[x] == -1) return x;
        return par[x] = root(par[x]);
    }
    bool unite(int x, int y) {
        int rx = root(x), ry = root(y);
        if(rx==ry)return false;
        if(rank[rx]<rank[ry]) swap(rx,ry);
        par[ry]=rx;
        if(rank[rx]==rank[ry]) rank[rx]++;
        siz[rx]+=siz[ry];
        return true;
    }
};

struct E {
    int id, a, b;
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N, M;
    int cnt=0;
    cin >> N >> M;
    vector<int> A(M), B(M);
    map<pii,int> mp;
    UnionFind uf(N);
    vector<E> extraEdges;
    REP(i, M) {
        cin >> A[i] >> B[i];
        A[i]--, B[i]--;
        // 自己ループや同じペアの場合は余剰扱い
        if(!mp.count({A[i],B[i]}) && A[i]!=B[i]){
            if(uf.unite(A[i],B[i])) {
                cnt++; // spanning tree に使った
            } else {
                extraEdges.push_back({i, A[i], B[i]});
            }
        } else {
            extraEdges.push_back({i, A[i], B[i]});
        }
        mp[{A[i],B[i]}] = 1;
    }
    
    // 各サーバーの連結成分(代表)は uf.root(i) により得られる
    vector<int> compList;
    REP(i,N) compList.push_back(uf.root(i));
    sort(ALL(compList));
    compList.erase(unique(ALL(compList)), compList.end());
    
    // 成分ごとに,その成分に属する余剰(変更可能)ケーブル候補を、端点情報付きで集める
    vector<vector<E>> extras(N);
    for(auto &e : extraEdges){
        int comp = uf.root(e.a);
        extras[comp].push_back(e);
    }
    
    // 貪欲に操作するため,まず変更可能なケーブル数が多い成分をメインに選ぶ
    int mainComp = compList[0];
    for(auto r : compList){
        if(extras[r].size() > extras[mainComp].size()){
            mainComp = r;
        }
    }
    
    // 操作 (ケーブル番号, 変更前のサーバー, 変更後のサーバー) を記録(内部は0-indexed; 出力時 +1)
    vector<tuple<int,int,int>> ops;
    // 各成分をメイン成分へ統合
    for(auto r : compList){
        if(r == mainComp) continue;
        // まず,余剰ケーブルがある成分側から利用できれば,その成分に記録してある端点(e.a)で再配線
        if(!extras[r].empty()){
            E candidate = extras[r].back();
            extras[r].pop_back();
            ops.push_back({candidate.id, candidate.a, mainComp});
        }
        // なければ,メイン側の余剰ケーブルから,端点を r に変更
        else if(!extras[mainComp].empty()){
            E candidate = extras[mainComp].back();
            extras[mainComp].pop_back();
            ops.push_back({candidate.id, candidate.a, r});
        }
        // マージ後,両成分の余剰候補を統合
        for(auto &e : extras[r])
            extras[mainComp].push_back(e);
    }
    
    cout << ops.size() << "\n";
    // 出力は1-indexedに変換して表示
    for(auto &op : ops){
        int cable, before, after;
        tie(cable, before, after) = op;
        cout << cable+1 << " " << before+1 << " " << after+1 << "\n";
    }
    
    return 0;
}

Submission Info

Submission Time
Task E - Cables and Servers
User una_o0
Language C++ 20 (gcc 12.2)
Score 450
Code Size 3607 Byte
Status AC
Exec Time 146 ms
Memory 28236 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 450 / 450
Status
AC × 3
AC × 22
Set Name Test Cases
Sample sample_01.txt, sample_02.txt, sample_03.txt
All random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt, sample_01.txt, sample_02.txt, sample_03.txt
Case Name Status Exec Time Memory
random_01.txt AC 70 ms 16288 KiB
random_02.txt AC 62 ms 15340 KiB
random_03.txt AC 6 ms 4508 KiB
random_04.txt AC 1 ms 3572 KiB
random_05.txt AC 108 ms 23448 KiB
random_06.txt AC 25 ms 11332 KiB
random_07.txt AC 8 ms 4900 KiB
random_08.txt AC 1 ms 3604 KiB
random_09.txt AC 75 ms 17408 KiB
random_10.txt AC 42 ms 11404 KiB
random_11.txt AC 108 ms 21720 KiB
random_12.txt AC 1 ms 3684 KiB
random_13.txt AC 129 ms 24988 KiB
random_14.txt AC 125 ms 24972 KiB
random_15.txt AC 128 ms 24904 KiB
random_16.txt AC 128 ms 25048 KiB
random_17.txt AC 146 ms 28236 KiB
random_18.txt AC 58 ms 24264 KiB
random_19.txt AC 2 ms 3500 KiB
sample_01.txt AC 1 ms 3500 KiB
sample_02.txt AC 1 ms 3492 KiB
sample_03.txt AC 1 ms 3552 KiB


2025-06-06 (Fri)
17:58:18 +09:00