紀中週末訓練 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; }