解析:
本题的意思是,求一个环的最小的那条边。
并且输出其这个环的点。
我们可以利用并查集,进行确定其是否有环路。在将所用的边从大到小排序。
利用 vector容器,pop_back() 和 push的特性。
起点为 u终点为 v寻找路径。
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
const int N = 2e5 + 10;
struct edge {int u, v, w;} e[N]; //存输入的所有边
vector<PII> graph[N]; //邻接表存图,first存通往的点, second存边权
int n, m, U, V, W, fa[N], vis[N];
vector<int> path; //存遍历顺序
bool cmp(edge a, edge b)
{
return a.w > b.w;
}
int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
} //并查集查询
void merge(int x, int y)
{
fa[find(x)] = find(y);
} //并查集合并
bool dfs(int now){
if(now == V){
return true; //找到答案,直接回溯
}
for(auto it: graph[now]){
if(it.second < W || vis[it.first]) continue;
vis[it.first] = true; //标记此点已走过
path.push_back(it.first);
if(dfs(it.first)) return true;
path.pop_back();
}
return false;
}
void solve(){
cin >> n >> m;
for(int i = 1; i <= n; i ++) fa[i] = i, graph[i].clear(), vis[i] = false; //初始化
for(int i = 1; i <= m; i ++) cin >> e[i].u >> e[i].v >> e[i].w; // 输入每一条边
path.clear();
sort(e + 1, e + 1 + m, cmp); //按边权从大到小排序
for(int i = 1; i <= m; i ++){
int u = e[i].u, v = e[i].v, w = e[i].w;
graph[u].push_back({v, w}), graph[v].push_back({u, w});
if(find(u) == find(v)){ //加入这条边之后会产生新的环
U = u, V = v, W = w; //此时w为最小边
}else{
merge(u, v);
}
}
path.push_back(U);
vis[U] = true;
dfs(U);
cout << W << " " << path.size() << "\n";
for(auto it: path) {cout << it << " ";}
cout << "\n";
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while(t--)
{
solve();
}
return 0;
}