判定
最初のマップは互いに素セットとチャイナユニコムは、宣告することができなければなりません
無向火Oula回路:全ての点は、度の偶数であります
Tuouラパスを無向:度の2点(点または0)度の奇数であり、残りの点(又はすべてのポイント)が偶数であります
ダイレクトTuouラ回路:=浸透のすべてのポイント
Tuouラパスを監督:アウト度ポイント度= +1、浸透のドット度アウト度= +1、残りの点(又はすべてのポイント)を=
-Hierholzerアルゴリズムを探します
//已知存在欧拉路径,找该路径
void dfs(int u){//s1~sn中存储的是欧拉路径上的点序列
for(int v=1;v<=n;v++){
if(mp[u][v]>0){
mp[u][v]--;
mp[v][u]--;
dfs(v);
}
}
s[temp--]=u;
}
なぜそれが正しいのですか?
片側が奇数加え、グラフ上の2点間のオイラー回路によって問題にオイラー経路を見つけることができるからです。オイラー図は環の数をネストすることによって形成されなければならない存在を列挙することによって求めることができる(二つにいくつかのポイントが約サボテンなど)
uが第一のサブサブリングに直面してリングを歩き回るように、リングなどのメインリングは、ストロークがいる限り、メインリングを終了するにはちょうど良いメインのリングに沿って歩行に続いてのポイントを、持っています
Hierholzerアルゴリズムは、我々は単純な実装の上にある思考の一種であります:
私たちは(あなたが実際にリングの必ずしも最も明白ではない、多くの異なる可能性がありますすることができます)、リングの主要部分を見回しのポイントDFSが開始されます、最初の時間は、再帰にできないDFS、すべてのポイントが横断しますメインリングであるあなたはこの点について説明を再帰的にすることができます場合は、まだ、配列にその答え再帰的にすることはできませんし、その後、後ろから前方に移動した場合、当時、存在している間、それは、配列への最終的な答えのポイントへの最終的なトラバースことは明らかです副リング、それに沿って副再帰ループは、我々はアルゴリズムをシミュレートし、後方の前にこのよう、背面のポイントに同じ最終トラバースです。
例:
ネックレス
https://vjudge.net/contest/347059#problem/C
各ビーズネックレスは、2つの側面、各側に1つの色を有し、ネックレス上の隣接するビーズの二つの隣接する面はかどうかを尋ねることによって、同じ色(ネックレスが環である)、ビーズおよびそれらの色の所定数でなければなりませんビーズの全てがネックレスに結合するのですか?
色の種類= 50
グラフ上の点と一つの色を出現、エッジが存在する存在する場合、それはそのようなオイラー図に明らかであり、それはネックレスで構成することができる(= 2色間のビーズのすべてのエッジを旅)ビーズのすべてを使い果たし。
互いに素セット+ Hierholzerアルゴリズムをすることができます。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+5;
int a[maxn],b[maxn];
int mp[55][55];
int du[55];
int s[maxn],tot,temp;
void dfs(int u){
for(int v=1;v<=50;v++){
if(mp[u][v]>0){
mp[u][v]--;
mp[v][u]--;
dfs(v);
}
}
s[temp--]=u;
}
int fa[55],vis[55];
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
int main(){
int T;
cin>>T;
for(int kase=1;kase<=T;kase++){
int n;
cin>>n;
for(int i=1;i<=50;i++)fa[i]=i;
memset(mp,0,sizeof(mp));
memset(du,0,sizeof(du));
memset(s,0,sizeof(s));
memset(vis,0,sizeof(vis));
tot=0;
for(int i=1;i<=n;i++){
int u,v;
scanf("%d%d",&u,&v);
vis[u]=vis[v]=1;
int fu=find(u),fv=find(v);
fa[fu]=fv;
mp[u][v]++;
mp[v][u]++;
du[u]++;
du[v]++;
tot++;
}
int cnt1=0;
for(int i=1;i<=50;i++){
if(vis[i]&&fa[i]==i)cnt1++;
}
if(cnt1>1){
printf("Case #%d\nsome beads may be lost\n",kase);
continue;
}
int flag=1;
for(int i=1;i<=50;i++){
if(du[i]&1){
flag=0;
break;
}
}
if(!flag){
printf("Case #%d\nsome beads may be lost\n",kase);
if(kase<=T)printf("\n");
continue;
}
temp=tot;
for(int i=1;i<=50;i++){//找一个点
if(vis[i]){
dfs(i);
break;
}
}
printf("Case #%d\n",kase);
for(int i=1;i<=tot;i++){
printf("%d %d\n",s[i],s[i%tot+1]);
}
if(kase<=T)printf("\n");
}
}