傳送門
一道非常不錯的尤拉迴路(路徑)題……
我們已經知道怎麼求尤拉迴路(路徑)了,但是如果求字典序最小的呢?
求尤拉迴路是乙個深搜的過程……所以我們不如每次在向下乙個點深搜的時候,每次讓他先走那個字典序最小的節點,這樣我們就能保證字典序最小了。不過實際上這個用鄰接表實現會很麻煩。我的實現方法是,對於所有的邊,我們先把它拆成兩條有向邊,對於拆出來的邊賦予相同的id,之後我們把邊按照起始點和終點排個序(注意鄰接表的儲存方法,終點要倒著排序),然後跑尤拉路徑即可。
這道題中,因為我們要乙個長為n+1的字串滿足n個字元對都出現過且僅出現一次,那我們就相當於是把每個字元對看成一條邊,在這個圖上求尤拉路徑(迴路),所以一開始要先判定它能否有尤拉路徑(迴路),之後就正常dfs。
對於起始點的選擇有些神奇。我們不是每次都取最小的就行,因為如果要是求尤拉路徑的話,我們必須強制選編號最小的奇點開始,如果要是求尤拉迴路直接從最小的點開始即可。
這種題其實用鄰接矩陣方便……而且好像這個資料範圍鄰接矩陣和鄰接表跑的一樣快。
看一下**。
#include#include#include
#include
#include
#include
#include
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using
namespace
std;
typedef
long
long
ll;const
int m = 20005
;const
int inf = 1000000009
;int
read()
while(ch >= '
0' && ch <= '9'
)
return ans *op;
}struct
edge
}e[m
<<1],q[m<<1
];int n,head[m],x,y,z,deg[m],ecnt = 1,minn = 100000,mpos = 100000
,cnt,ans[m],tot;
char s[10
];bool
vis[m];
void add(int x,int y,int
z)void dfs(int
x) }
}int
main()
sort(q+1,q+1+(n<<1
)); rep(i,
1,n<<1
)
//rep(i,1,100) printf("%d ",deg[i]);enter;
rep(i,1,100) if((deg[i]>>1)&1) tot++;
if(tot > 2
)
rep(i,
1,100) if(i < mpos && (deg[i]>>1) & 1) mpos =i;
if(mpos == 100000) ans[++cnt] = q[1].from,dfs(q[1].from
);
else ans[++cnt] =mpos,dfs(mpos);
if(cnt != n+1) printf("
no solution\n");
else
return0;
}
無序字母對
問題描述 給定n個各不相同的無序字母對 區分大小寫,無序即字母對中的兩個字母可以位置顛倒 請構造乙個有n 1個字母的字串使得每個字母對都在這個字串中出現。輸入格式 第一行輸入乙個正整數n。以下n行每行兩個字母,表示這兩個字母需要相鄰。輸出格式 輸出滿足要求的字串。如果沒有滿足要求的字串,請輸出 no...
無序字母對
題目描述 給定n個各不相同的無序字母對 區分大小寫,無序即字母對中的兩個字母可以位置顛倒 請構造乙個有n 1個字母的字串使得每個字母對都在這個字串中出現。輸入輸出格式 輸入格式 第一行輸入乙個正整數n。以下n行每行兩個字母,表示這兩個字母需要相鄰。輸出格式 輸出滿足要求的字串。如果沒有滿足要求的字串...
無序字母對
剛開始學尤拉迴路,因為不太理解導致 wa 了兩次。錯點 度數為奇數個的點數大於2時不存在尤拉路徑 是偶數個也不行 如果存在尤拉路徑而不是尤拉迴路時,不能隨便選乙個點當做起點,必須選度數為奇數的兩個點中的乙個。include include includeusing namespace std con...