题目描述
给定一张$n$个点$m$条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通你想在这张图上进行若干次旅游,每次旅游可以任选一个点$x$作为起点,再走到一个与 $x$直接有边相连的点$y$,再走到一个与$y$直接有边相连的点$z$并结束本次旅游
作为一个旅游爱好者,你不希望经过任意一条边超过一次,注意一条边不能即正向走一次又反向走一次,注意点可以经过多次,在满足此条件下,你希望进行尽可能多次的旅游,请计算出最多能进行的旅游次数并输出任意一种方案
输入格式
第$1$行两个正整数$n$与$m$,表示全图的点数与边数
下接$m$行,每行两个数字$u$与$v$表示一条边
输出格式
第$1$行一个整数$cnt$表示答案
下接$cnt$行,每行三个数字$x,y$与$z$,表示一次旅游的路线
如有多种旅行方案,任意输出一种即可
样例
样例输入:
4 5
1 2
3 2
2 4
3 4
4 1
样例输出:
2
4 1 2
4 3 2
数据范围与提示
对于前$20\%$的数据,$n\leqslant 10,m\leqslant 20$
对于令$20\%$的数据,$m=n−1$,并且图连通
对于令$10\%$的数据,每个点的度数不超过$2$
对于$100\%$的数据,$n\leqslant 100,000,m\leqslant 200,000$
题解
如果你做过下面这两道题的其中一道,这道题就会显得简单多了:
题不一样,但是思路是类似的。
对于树和链,我们显然是从叶子节点开始一定最优。
那么考虑一般情况,利用上面那两道题的思路(尤其是虎),也有点类似无修支配树,总之都是贪心……
时间复杂度:$\Theta(n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h> using namespace std; struct rec{int nxt,to;}e[400001]; struct node{int x,y,z;}; int head[100001],cnt=1; int n,m; int depth[100001]; vector<node> ans; void add(int x,int y) { e[++cnt].nxt=head[x]; e[cnt].to=y; head[x]=cnt; } int dfs(int x) { int res=0; for(int i=head[x];i;i=e[i].nxt) { if(!depth[e[i].to]) { depth[e[i].to]=depth[x]+1; int flag=dfs(e[i].to); if(flag)ans.push_back((node){flag,e[i].to,x}); else { flag=e[i].to; if(res){ans.push_back((node){flag,x,res});res=0;} else res=flag; } } else { if(depth[e[i].to]>depth[x]) { int flag=e[i].to; if(flag) { if(res){ans.push_back((node){flag,x,res});res=0;} else res=flag; } } } } return res; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=n;i++) if(!depth[i]) { depth[i]=1; dfs(i); } printf("%d\n",ans.size()); for(int i=0;i<ans.size();i++)printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].z); return 0; }
rp++
原文地址:https://www.cnblogs.com/wzc521/p/11629289.html
时间: 2024-10-08 16:04:33