洛谷P2731題解
傳送錨點
摸魚環節
[USACO3.3] 騎馬修柵欄 Riding the Fences
題目背景
Farmer John 每年有很多柵欄要修理。他總是騎著馬穿過每一個柵欄並修復它破損的地方。
題目描述
John 是一個與其他農民一樣懶的人。他討厭騎馬,因此從來不兩次經過一個柵欄。
John 的農場上一共有 \(m\) 個柵欄,每一個柵欄連線兩個頂點,頂點用 \(1\) 到 \(500\) 標號(雖然有的農場並沒有那麼多個頂點)。一個頂點上至少連線 \(1\) 個柵欄,沒有上限。兩頂點間可能有多個柵欄。所有柵欄都是連通的(也就是你可以從任意一個柵欄到達另外的所有柵欄)。John 能從任何一個頂點(即兩個柵欄的交點)開始騎馬,在任意一個頂點結束。
你需要求出輸出騎馬的路徑(用路上依次經過的頂點號碼錶示),使每個柵欄都恰好被經過一次。如果存在多組可行的解,按照如下方式進行輸出:如果把輸出的路徑看成是一個 \(500\) 進位制的數,那麼當存在多組解的情況下,輸出 \(500\) 進製表示法中最小的一個 (也就是輸出第一位較小的,如果還有多組解,輸出第二位較小的,以此類推)。
輸入資料保證至少有一個解。
輸入格式
第一行一個整數 \(m\),表示柵欄的數目。
從第二行到第 \((m+1)\) 行,每行兩個整數 \(u,v\),表示有一條柵欄連線 \(u,v\) 兩個點。
輸出格式
共 \((m+1)\) 行,每行一個整數,依次表示路徑經過的頂點號。注意資料可能有多組解,但是隻有上面題目要求的那一組解是認為正確的。
資料保證至少有一組可行解。
樣例 #1
樣例輸入 #1
9
1 2
2 3
3 4
4 2
4 5
2 5
5 6
5 7
4 6
樣例輸出 #1
1
2
3
4
2
5
4
6
5
7
提示
對於 \(100\%\) 的資料,\(1 \leq m \leq 1024,1 \leq u,v \leq 500\)。
題目翻譯來自NOCOW。
USACO Training Section 3.3
這一把熟人局,老將Farmer john申請出戰還是日常幫助Farmer john處理休閒問題。今日份的john也是閒的蛋疼騎上了馬。不出意外的話就要出題,他居然還想修柵欄,直接幹出一道尤拉路徑。
正片開始
- 我們選擇用vector存個圖,並將每個點所連線的點按照大小排序,以此處理輸出順序。
code:
for(int i=1;i<=m;i++)
{
int u,v;cin>>u>>v;
g[u].push_back(v);g[v].push_back(u);
b[u][v]++,b[v][u]++;n=max(n,max(u,v));
}
for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end());
- 開始搞點,不斷遍歷每個點的臨界點,在\(a\)到\(b\)有邊的情況下進行遞迴處理,並將邊刪除以免重複計算。
code:
void findx(int x)
{
for(int i=0;i<g[x].size();i++)
{
if(b[x][g[x][i]]>0)
{
b[x][g[x][i]]--,b[g[x][i]][x]--;
findx(g[x][i]);
}
}
ans[++l]=x;
}
- 特判不是尤拉回路的情況,即存在\(g[i].size()\)為奇數。
code:
for(int i=1;i<=n;i++)
{
if(g[i].size()%2)
{
findx(i);f=1;
break;
}
}
if(f==0)
{
for(int i=1;i<=n;i++)
{
if(g[i].size())
{
findx(i);
break;
}
}
}
for(int i=l;i>=1;i--) cout<<ans[i]<<endl;
完整程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10;
int m,b[N][N],ans[N],l=0,n=0,f=0;
vector<int>g[N];
void findx(int x)
{
for(int i=0;i<g[x].size();i++)
{
if(b[x][g[x][i]]>0)
{
b[x][g[x][i]]--,b[g[x][i]][x]--;
findx(g[x][i]);
}
}
ans[++l]=x;
}
int main()
{
cin>>m;
for(int i=1;i<=m;i++)
{
int u,v;cin>>u>>v;
g[u].push_back(v);g[v].push_back(u);
b[u][v]++,b[v][u]++;n=max(n,max(u,v));
}
for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end());
for(int i=1;i<=n;i++)
{
if(g[i].size()%2)
{
findx(i);f=1;
break;
}
}
if(f==0)
{
for(int i=1;i<=n;i++)
{
if(g[i].size())
{
findx(i);
break;
}
}
}
for(int i=l;i>=1;i--) cout<<ans[i]<<endl;
return 0;
}
完結收工!!!!!
個人主頁
看完點贊,養成習慣
\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)