第46屆ICPC澳門站 K - Link-Cut Tree // 貪心 + 並查集 + DFS
阿新 • • 發佈:2022-04-08
原題連結:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com)
題意:
要求一個邊權值總和最小的環,並從小到大輸出邊權值(2的次冪);若不存在環,輸出-1。
思路:
#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;
}