1. 程式人生 > 實用技巧 >紀中週末訓練 2020.12.19【NOIP提高A組】模擬 T2:【NOIP2017提高A組模擬10.10】Graph

紀中週末訓練 2020.12.19【NOIP提高A組】模擬 T2:【NOIP2017提高A組模擬10.10】Graph

快兩個月沒更新了,不得不說最近真的有點忙,今天比賽的題目蠻好的,於是忙裡偷閒來分享一下

【NOIP2017提高A組模擬10.10】Graph

Description

給定一張n個點m條邊的無向圖,每條邊連線兩個頂點,保證無重邊自環,不保證連通
你想在這張圖上進行若干次旅遊,每次旅遊可以任選一個點x作為起點,再走到一個與x 直接有邊相連的點y,再走到一個與y 直接有邊相連的點z 並結束本次旅遊
作為一個旅遊愛好者,你不希望經過任意一條邊超過一次,注意一條邊不能即正向走一次又反向走一次,注意點可以經過多次,在滿足此條件下,你希望進行儘可能多次的旅遊,請計算出最多能進行的旅遊次數並輸出任意一種方案

Input

第1 行兩個正整數n 與m,表示全圖的點數與邊數
下接m 行,每行兩個數字u 與v 表示一條邊

Output

第1 行一個整數cnt 表示答案
下接cnt 行,每行三個數字x, y 與z,表示一次旅遊的路線
如有多種旅行方案,任意輸出一種即可

Sample Input

4 5
1 2
3 2
2 4
3 4
4 1

Sample Output

2
2 3 4
4 2 1

Data Constraint

對於前20% 的資料,n <= 10;m <= 20.
對於令20% 的資料,m = n - 1,並且圖連通
對於令10% 的資料,每個點的度數不超過2
對於100% 的資料,n <= 100000;m <= 200000

題解

比賽的時候以為頭尾要相連結果直接棄療,比完賽後聽別人講發現看錯題了……其實不算很難
首先這題不保證圖連通,就是可以把每個連通塊分來來處理,其實也沒鳥用
我們先看當一個連通塊是樹的情況
很顯然從下往上處理,對於一個節點將他的所有兒子節點經過這個節點兩兩匹配,如果剩一個就跟這個節點與他父親的那一條邊匹配,這種方法的正確性顯然,因為不會遺漏每一條邊
但是如果不是樹能不能這樣處理呢?其實是可以的,我們只要分好層,有一些邊即使忽略不計也是不會影響到答案的
大家可以畫個圖自行理解理解

CODE

最近學了學壓行和卡常,程式碼可能寫得有點兒醜……

#include<cstdio>
#include<string>
#include<cstring>
#define R register int
#define N 100005
using namespace std;
struct arr{int to,next;}edge[N<<2];
int n,m,cnt=-1,fa[N],tb[N<<2],ans,ans1[N<<2][3],head[N];
bool bzd[N],bzb[N<<2];
inline void read(int &x)
{
	x=0;char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
}
inline void add(int u,int v) {edge[++cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;}
inline void dfs(int now,int num)
{
	bzd[now]=true;bool choose=false;int choosenum;
	for (R i=head[now];i!=-1;i=edge[i].next)
	{
		int v=edge[i].to,vb=i;if (!bzd[v]) fa[v]=now,dfs(v,i);
		if (!bzb[i] && v!=fa[now])
		{
			if (choose)
			{
				choose=false;
				ans1[++ans][0]=edge[choosenum].to;ans1[ans][1]=now;ans1[ans][2]=v;
				bzb[choosenum]=bzb[choosenum^1]=bzb[i]=bzb[i^1]=true;
			}
			else choose=true,choosenum=i;
		}
	}
	if (now!=fa[now] && choose)
	{
		ans1[++ans][0]=edge[choosenum].to;ans1[ans][1]=now;ans1[ans][2]=edge[num^1].to;
		bzb[choosenum]=bzb[choosenum^1]=bzb[num]=bzb[num^1]=true;
	} 	
}
int main()
{
	freopen("graph.in","r",stdin);
	freopen("graph.out","w",stdout);
	read(n);read(m);
	memset(head,-1,sizeof(head));
	for (R i=1;i<=m;++i)
	{
		int x,y;read(x);read(y);
		add(x,y);add(y,x);
	}
	for (R i=1;i<=n;++i)
		if (!bzd[i]) fa[i]=i,dfs(i,0);
	printf("%d\n",ans);
	for (R i=1;i<=ans;++i)
		printf("%d %d %d\n",ans1[i][0],ans1[i][1],ans1[i][2]);
	return 0;
}