欧拉路径
借鉴文章
\(1\). 欧拉路径定义:
图中经过所有边恰好一次的路径叫欧拉路径(也就是一笔画)。如果此路径的起点和终点相同,则称其为一条欧拉回路。
\(2.\) 欧拉路径判定(是否存在):
-
有向图欧拉路径:图中恰好存在 \(1\) 个点出度比入度多 \(1\)(这个点即为 起点 \(S\)),\(1\) 个点入度比出度多 \(1\)(这个点即为 终点 \(T\)),其余节点出度=入度。
-
有向图欧拉回路:所有点的入度=出度(起点 \(S\) 和终点 \(T\) 可以为任意点)。
-
无向图欧拉路径:图中恰好存在 \(2\) 个点的度数是奇数,其余节点的度数为偶数,这两个度数为奇数的点即为欧拉路径的 起点 \(S\) 和 终点 \(T\)。
-
无向图欧拉回路:所有点的度数都是偶数(起点 \(S\) 和终点 \(T\) 可以为任意点)。
注:存在欧拉回路(即满足存在欧拉回路的条件),也一定存在欧拉路径。
当然,一副图有欧拉路径,还必须满足将它的有向边视为无向边后它是连通的(不考虑度为 \(0\) 的孤立点),连通性的判断我们可以使用并查集
或 dfs
等。
例题
欧拉路径
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1e5+5;
std::vector<int> edge[N];
int n,m;
int in[N],out[N],cnt[2],del[N];
stack <int> sta;bool vis[N];
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
edge[u].push_back(v);
out[u]++;in[v]++;
}
for(int i=1;i<=n;i++) sort(edge[i].begin(),edge[i].end());
bool equal=1;int st=1;//注意默认起点
for(int i=1;i<=n;i++)
{
if(out[i]!=in[i])
{
equal=0;
if(out[i]-in[i]==1)cnt[1]++,st=i;
else if(in[i]-out[i]==1)cnt[0]++;
else return cout<<"No"<<endl,0;
}
}
if((!equal)&&!(cnt[0]==cnt[1]&&cnt[0]==1)) return cout<<"No"<<endl,0;
auto dfs=[&](auto dfs,int u) ->void{
for(int i=del[u];i<edge[u].size();i=del[u])
{
del[u]=i+1;int to=edge[u][i];
dfs(dfs,to);
}
sta.push(u);
};
dfs(dfs,st);
while(sta.size())cout<<sta.top()<<" ",sta.pop();
return 0;
}
骑马修栅栏
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1e4+5;
std::vector<int> edge[N];
int n,m;
int du[N],mp[N][N],st;
stack <int> sta;bool vis[N];
int mi=1e9;
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>m;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
mp[u][v]++;mp[v][u]++;
du[u]++;du[v]++;
n=max(n,u);n=max(n,v);
mi=min(u,mi);mi=min(mi,v);
}
st=mi;//注意默认起点
for(int i=1;i<=n;i++)
{
du[i]%2?({st=i;break;}):({continue;});
}
auto dfs=[&](auto dfs,int u) ->void{
for(int i=1;i<=n;i++)
{
if(mp[u][i])
{
mp[u][i]--;
mp[i][u]--;
dfs(dfs,i);
}
}
sta.push(u);
};
dfs(dfs,st);
while(sta.size())cout<<sta.top()<<endl,sta.pop();
return 0;
}
P1341 无序字母对
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 250+5;
int n;
stack <char> sta;
char mp[N][N];
char du[N];
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n;
char op[3];
char st=0;
for(int i=1;i<=n;i++)
{
cin>>op;
mp[op[0]][op[1]]=1;
mp[op[1]][op[0]]=1;
du[op[1]]++;du[op[0]]++;
}
// cout<<st<<endl;
int cnt=0;
for(char i='A';i<='z';i++)
{
if(i>'Z'&&i<'a')i='a';
if(du[i]%2)
{
cnt++;
if(!st)st=i;
// break;
}
}
if(!st)
{
for(char i='A';i<='z';i++)
{
if(i>'Z'&&i<'a')i='a';
// cout<<i<<endl;
if(du[i])
{
st=i;break;
}
}
}
auto dfs=[&](auto dfs,char u) ->void{
// cout<<u<<endl;
for(char i='A';i<='z';i++)
{
if(i>'Z'&&i<'a')i='a';
if(mp[u][i]>0)
{
// cout<<mp[u][i]<<endl;
mp[u][i]--;
mp[i][u]--;
dfs(dfs,i);
}
}
// cout<<u<<endl;
sta.push(u);
};
dfs(dfs,st);
if((cnt&&cnt!=2)||sta.size()<n+1)
{
cout<<"No Solution"<<endl;
return 0;
}
while(sta.size())cout<<char(sta.top()),sta.pop();
return 0;
}
P1127 词链
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 2000+5;
int n;
string s[N];bool used[N];
int in[N],out[N];
vector <int> edge[N];
void dfs(int S, std::string curr, int count) {
if (count == n) {
curr[curr.length() - 1] = ' ';
std::cout << curr;
exit(0);
}
for (auto i : edge[S])
if (!used[i]) {
used[i] = true;
dfs(i, curr + s[i] + '.', count + 1);
used[i] = false;
}
}
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
int len=s[i].size()-1;
in[s[i][0]]++;out[s[i][len]]++;
}
std::sort(s + 1, s + n + 1);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (i != j && s[i][s[i].length() - 1] == s[j][0])
edge[i].push_back(j);
for (int i = 1; i <= n; ++i)
if (in[s[i][0]] == out[s[i][0]] + 1) {
used[i] = true;
dfs(i, s[i] + '.', 1);
used[i] = false;
}
used[1] = true;
dfs(1, s[1] + '.', 1);
used[1] = false;
std::cout << "***";
return 0;
}
思路:我们可以类似\(hash\)把前\(m-1\)位表示为\(n\)进制下的数,第m位看成m个边,这样所有状态都能表示出来,跑欧拉回路,具体连边为后\(\sum_{x=0}^{n-1}436653->36653x\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1E6+5;
int n,m,cnt,f[N],del[N],vis[N];
vector <pii> edge[N];
stack <int> sta;
void calc(int len,int sum)
{
if(len==m-1)
{
f[++cnt]=sum;
return;
}
for(int i=0;i<=n-1;i++)
{
calc(len+1,sum*n+i);
}
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>m;
if(n==1)
{
cout<<m<<endl;
for(int i=1;i<=m;i++)
{
cout<<0<<" ";
}
}
else if(m==1)
{
cout<<n<<endl;
for(int i=0;i<=n-1;i++)cout<<i<<" ";
}else
{
calc(0,0);
ll p=pow(n,m-2);int tot=0;
for(int i=1;i<=cnt;i++)
{
for(int j=0;j<=n-1;j++)
{
tot++;
edge[i].pb({lower_bound(f+1,f+1+cnt,(f[i]%p)*n+j)-f,tot});
//含义为一个n进制数 12345*
*23451这种方式相连 //
// cout<<f[i]<<" "<<lower_bound(f+1,f+1+cnt,(f[i]%p)*n+j)-f<<endl;
}
}
auto dfs=[&](auto dfs,int x)->void{
for(int i=del[x];i<(int)edge[x].size();i=max(del[x],i+1))
{
if(vis[edge[x][i].second]==0)
{
vis[edge[x][i].second]=1;
del[x]=i+1;
dfs(dfs,edge[x][i].first);
}
}
sta.push(x);
};
dfs(dfs,1);
cout<<sta.size()-1<<endl;
while(sta.empty()==0)
{
int x=sta.top();
sta.pop();
if(sta.empty()==0)
{
cout<<f[sta.top()]-(f[x]%p)*n<<" ";
}
}
}
return 0;
}