zoukankan      html  css  js  c++  java
  • CodeForces

    题目链接

    题目大意

      给你一个无向图问是否可以构造一颗生成树,使1号点的度数为d。

    解题思路

      先把与1号点相连的边的权值都改成INF,其他是0,这样的话如果还用权值为INF的边,说明这些边是必不可少的,如果使用的权值为INF的边大于d,必定无解。否则,将之前必须用到的与1相连边的权值设成-1,其他与1相连的边设成0,其他边设成1,再跑一遍最小生成树就行了,与1相连的边使用到d条之后就不用了。

    代码

    const int maxn = 2e5+10;
    const int maxm = 2e5+10;
    int n, m, d, deg[maxn], p[maxn];
    int find(int x) {
    	return p[x]==x ? p[x]:p[x]=find(p[x]);
    }
    struct I {
    	int u, v, w;
    } e[maxn];
    int main() {
    	cin >> n >> m >> d;
    	for (int i = 1, a, b; i<=m; ++i) {
    		cin >> e[i].u >> e[i].v;
    		if (e[i].u==1 || e[i].v==1) e[i].w = INF;
    		++deg[e[i].u];
    		++deg[e[i].v];
    	}
    	sort(e+1, e+m+1, [](I a, I b) {return a.w<b.w;});
    	for (int i = 1; i<=n; ++i) p[i] = i;
    	int cnt = 0;
    	for (int i = 1; i<=m; ++i) {
    		int fa = find(e[i].u);
    		int fb = find(e[i].v);
    		if (fa!=fb) {
    			p[fa] = fb;
    			if (e[i].w==INF) {
    				e[i].w = -1;
    				++cnt;
    			}
    		}
    	}
    	if (cnt>d || deg[1]<d) {
    		cout << "NO" << endl;
    		return 0;
    	}
    	for (int i = 1; i<=m; ++i) {
    		if (e[i].w==INF) e[i].w = 0;
    		else if (!e[i].w) e[i].w = 1;
    	}
    	sort(e+1, e+m+1, [](I a, I b) {return a.w<b.w;});
    	for (int i = 1; i<=n; ++i) p[i] = i;
    	vector<P> ans;
    	for (int i = 1; i<=m; ++i) {
    		int fa = find(e[i].u);
    		int fb = find(e[i].v);
    		if (fa!=fb && ((e[i].w<=0 && d) || e[i].w)) {
    			p[fa] = fb;
    			if (e[i].w<=0) --d;
    			ans.push_back({e[i].u, e[i].v});
    		}
    	}
    	cout << "YES" << endl;
    	for (auto v : ans) printf("%d %d
    ", v.x, v.y);
    	return 0;
    } 
    
  • 相关阅读:
    vim
    Linux 软链接和硬链接
    常用命令
    linux 二级目录结构
    关于bash shell的理解
    虚拟机网络模式
    安装虚拟机
    date 命令
    使用3种协议搭建yum仓库
    ubuntu update时发生错误
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/14438866.html
Copyright © 2011-2022 走看看