2024“钉耙编程”中国大学生算法设计超级联赛(8)1006 cats 的最小生成树

题目大意 :给出有n个点m条边的图,接下来进行若干次操作,每次操作取出当前图的最小生成树,然后删去这些构成最小生成树的边,知道该图不连通,输出每条边在第几次操作时被删除
思路 :由于构成最小生成树的边数是n1条边,所以最多操作次数为mn1,每次操作都会有一个并查集(kruskal)所以创建mn1个并查集,从小到大遍历所有的边,看看属于哪个并查集,即在第几次被删除,找到的第一个不连通的并查集即为该边所在的并查集,找到后将这个边插入该并查集,即将u,v合并(同祖先),并将该并查集操作次数+1。操作完后访问所有的边,判断其所在并查集是否操作了n1次,如果为否输出-1,否侧输出该边属于第几个并查集(该边第几次删除)

#include <bits/stdc++.h>  
  
  
const double eps = 1e-6;  
using namespace std;  
  
const int N = 1e5 + 10;  
const int M = 5e4 + 10;  
  
#define int  long long  
  
struct node {  
    int u, v, val;  
};  
  
  
void solve() {  
    int n, m;  
    cin >> n >> m;  
    vector<vector<int> > fa(m / (n - 1) + 1, vector<int>(n + 1));  
    vector<node> E(m + 1);  
    vector<int> ans(m + 1), cnt(m + 1);  
    function<int(int, int)> findf = [&](int x, int c) -> int {  
        if (fa[c][x] == x) return x;  
        else return fa[c][x] = findf(fa[c][x], c);  
    };  
    for (int j = 0; j <= (m / (n - 1)); j++) {  
        for (int i = 1; i <= n; i++) {  
            fa[j][i] = i;  
            //cout<<"fa[" << j <<"]["<<i << "]="<<fa[j][i]<<'\n';  
        }  
    }  
    //cout << fa[1][1] << '\n';  
    for (int i = 1; i <= m; i++) {  
        int u, v;  
        cin >> u >> v;  
        E[i] = {u, v, i};  
    }  
    for (int i = 1; i <= m; i++) {  
        auto [u, v, w] = E[i];  
        int l = 1, r = m / (n - 1);  
        int idx = -1;  
        while (l <= r) {  
            int mid = (l + r) >> 1;  
            //cout << findf(u, mid) << ' ' << findf(v, mid) << '\n';  
            if (findf(u, mid) == findf(v, mid)) {  
                l = mid + 1;  
            } else {  
                idx = mid;  
                r = mid - 1;  
            }  
        }  
        if (idx != -1) {  
            fa[idx][findf(u, idx)] = findf(v, idx);  
            cnt[idx]++;  
        }  
        ans[i] = idx;  
    }  
    for (int i = 1; i <= m; i++) {  
        if (ans[i] == -1) cout << -1;  
        else if (ans[i] == m / (n - 1) + 1 || cnt[ans[i]] != n - 1) cout << "-1";  
        else cout << ans[i];  
        cout << ' ';  
    }  
    cout << '\n';  
}  
  
signed main() {  
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);  
    int _ = 1;  
    cin >> _;  
    while (_--) solve();  
}
posted @   yoez123  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示