此题标难度2500,场内ac4人,因为是一开始的cf,段位都不高就给的分低了。可能有2700分。
欧拉路径好题
题意:给你一个无向图,问能否输出两条路径,使得遍历所有边。
思路:很显然,一眼能想到欧拉路径,但是两条看似简单,其实要想很多。
- m==1 此时输出-1
- 只有一个联通块,那么我们仔细想一下,当度数为0,2,4的时候是可以的,0 和 2很显然。但4怎么搞,这是一个这道题比较难也比较亮的一点。我的做法是给两个奇度加边,然后输出的时候隔离这个加边。那么我们来证明一下吧,无向图的欧拉路径只要满足a. 联通 b. 奇度为0,和奇度为2,此时可以。那么我们输出两条路径,等价于我们把4个奇度两个相连变为一个2奇度的图,然后跑欧拉路径,之后只要隔离这条边就行了。
- 两个联通块,每个块度数为0,2时可以。
有个大佬用图解的方法写出来了:https://www.luogu.org/blog/user56917/solution-cf36e
我的代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0)
const int maxn = 1e4+5;
//vector<int>zz;
int head[maxn],deg[maxn],ans[maxn],vis[maxn],tot,sum,cnt,cnt2;
bool a[maxn];
struct edge{
int v,nex;
bool ok;
}e[maxn<<1];
void init(){
forn(i,maxn) head[i] = -1;
tot = 0;
}
void add(int u,int v){
e[tot] = {v,head[u],0};
head[u] = tot++;
}
void dfs(int u){
vis[u] = cnt;
//cerr<<"@!#!@ "<<u<<' '<<cnt<<'
';
for(int i = head[u];i!=-1;i = e[i].nex){
int v = e[i].v;
if(!vis[v]) dfs(v);
}
}
void euler(int u){
for(int i = head[u];i!=-1;i = e[i].nex){
int v = e[i].v;
if(e[i].ok) continue;
e[i].ok = 1,e[i^1].ok = 1;
euler(v);
//cerr<<"asdas "<<u<<' '<<v<<'
';
ans[++sum] = i+2>>1;
}
//zz.push_back(u);
}
int main(){
IO;
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
init();
int m;cin>>m;
if(m==1) return cout<<-1<<'
',0;
forn(i,m){
int u,v;cin>>u>>v;
deg[u]++,deg[v]++;
//cerr<<deg[u]<<' '<<deg[v]<<'
';
a[u] = a[v] = 1;
add(u,v),add(v,u);
}
for1(i,maxn-5) if(!vis[i]&&a[i]) cnt++,dfs(i);
if(cnt>2) return cout<<-1<<'
',0;
if(cnt==1){
cnt = 0;
for1(i,maxn-5) if(deg[i]&1) cnt++;
if(cnt!=2&&cnt!=4&&cnt!=0) return cout<<-1<<'
',0;
if(cnt==0){
for1(i,maxn-5) if(a[i]) {
euler(i);
break;
}
cout<<m-1<<'
';
for(int i = m;i>1;i--) cout<<ans[i]<<' ';
cout<<'
';
cout<<1<<'
';
cout<<ans[1]<<'
';
}else if(cnt==2){
for1(i,maxn-5) if(deg[i]&1){
euler(i);
break;
}
cout<<m-1<<'
';
//cerr<<"!@#@!# "<<sum<<' '<<m<<'
';
for(int i = m;i>1;i--) cout<<ans[i]<<' ';
cout<<'
';
cout<<1<<'
';
cout<<ans[1]<<'
';
}else{
vector<int>odd;
for1(i,maxn-5) if(deg[i]&1) odd.push_back(i);
add(odd[1],odd[2]);
add(odd[2],odd[1]);
//cerr<<odd[0]<<'
';
euler(odd[0]);
//cerr<<"!@##@! "<<sum<<' '<<m<<'
';
//reverse(zz.begin(),zz.end());
//for(auto &x:zz) cerr<<x<<' ';
// cerr<<'
';
while(1){
if(ans[sum]>m) break;
sum--;
}
cout<<m+1-sum<<'
';
for(int i = m+1;i>sum;i--) cout<<ans[i]<<' ';
sum--;
cout<<'
';
cout<<sum<<'
';
for(int i = sum;i>=1;i--) cout<<ans[i]<<' ';
}
return 0;
}
//cerr<<"@!#!@# "<<'
';
cnt = 0;
for1(i,maxn) if(deg[i]&1){
//cerr<<"!@#!@# "<<i<<' '<<vis[i]<<'
';
if(vis[i]==1) cnt++;
else cnt2++;
}
//cerr<<cnt<<' '<<cnt2<<'
';
if(cnt!=0&&cnt!=2) return cout<<-1<<'
',0;
if(cnt2!=0&&cnt2!=2) return cout<<-1<<'
',0;
if(cnt==0){
for1(i,maxn) if(vis[i]==1){
euler(i);
break;
}
}else{
for1(i,maxn) if((deg[i]&1)&&vis[i]==1){
euler(i);
//cerr<<"@!#@# "<<i<<'
';
break;
}
}
cout<<sum<<'
';
for(int i = sum;i>=1;i--) cout<<ans[i]<<' ';
cout<<'
';
sum = 0;
if(cnt2==0){
for1(i,maxn) if(vis[i]==2){
euler(i);
break;
}
}else{
for1(i,maxn) if((deg[i]&1)&&vis[i]==2){
euler(i);
break;
}
}
cout<<sum<<'
';
for(int i = sum;i>=1;i--) cout<<ans[i]<<' ';
cout<<'
';
return 0;
}
/*
9
1 2
2 3
3 4
4 5
5 2
4 6
6 7
7 8
8 6
*/