第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS
2024-10-20 20:40:15
原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com)
题意:
要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂);若不存在环,输出-1。
思路:
考虑按权值从小到大加边,当出现环时(利用并查集判环),这个环必定是总权值最小的环。
找到环后,不再加边,并从环上某一点做DFS,找到从该点出发并再次回到该点的环。
代码:
#include <bits/stdc++.h>
#define PII pair<int,int>
#define fi first
#define se second
using namespace std; const int N = 100010; int n, m, fa[N], stk[N], top;
vector<PII> v[N];
bool vis[N], mark; int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
} void dfs(int u, int pre, int ed)
{
if(mark) return;
if(u == ed && ~pre) {
mark = true;
sort(stk + 1, stk + 1 + top);
for(int i = 1; i <= top; i++) printf("%d ", stk[i]);
cout << endl;
}
for(auto i : v[u]) {
if(vis[i.fi] || i.fi == pre) continue;
stk[++top] = i.se, vis[i.fi] = true;
dfs(i.fi, u, ed);
-- top, vis[i.fi] = false;
}
} void solve()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) {
fa[i] = i, vis[i] = false;
v[i].clear();
}
int st = 0;
bool flag = false; // 是否存在环
for(int i = 1; i <= m; i++) {
int x, y;
scanf("%d%d", &x, &y);
if(flag) continue;
v[x].push_back({y, i}), v[y].push_back({x, i});
int fx = find(x), fy = find(y);
if(fx == fy) flag = true, st = x;
else fa[fx] = fy;
}
if(!flag) puts("-1");
else mark = false, dfs(st, -1, st);
} int main()
{
int test;
cin >> test;
while(test--) solve(); return 0;
}
最新文章
- 新版react踩坑总结
- (一)观察者模式-C++实现
- 论javascript中的原始值和对象
- (转)Array.prototype.slice.call自解
- [转]JDK6和JDK7中的substring()方法
- (转)HTML5 本地存储
- JDBC和JPA调用储存过程 接收存储过程有返回值
- Linux系统中,main函数的执行过程
- [Hapi.js] Managing State with Cookies
- UML简单梳理类图
- eclipse中debug快捷方式
- 屏蔽ps联网激活
- JS解析JSON字符串
- python使用正则解析网络地址的各个部分
- ES6新增对象方法的访问描述符:get(只读)、set(只写)
- WebView 安全之 addJavascriptInterface
- MJRefresh在Xode6中报错处理
- Python学习笔记【第十篇】:Python面向对象进阶
- excel 2007 无法输入中文
- 如何设置java环境变量