【题解】CF2110E Melody

一:【题意】

给你 \(n\) 个二元组,要求满足:
1.对于每个 \(i,a[i]=a[i+1] or b[i]=b[i+1]\)
2.对于每个 \(i\) 都不能有 \(a[i]=a[i+1]=a[i+2]\)\(b[i]=b[i+1]=b[i+2]\)
问是否有解,如果有输出方案
\(n<=2 \times 10^5\)

二:【解法】

\(a_{1...n}\)\(b_{1...n}\) 的值域上考虑,建立 \(2*n\) 个点
如果存在二元组 \((a_i,b_i)\) ,那么在 \(a_i\)\(b_i\) 对应的节点之间连边
容易发现这是张二分图,问题也转化成了求二分图上的欧拉路径
记录边编号

三:【代码】

#include<bits/stdc++.h>
#define Pair pair<int,int>
#define v first
#define id second
using namespace std;
typedef long long LL;
const int N=4e5+10;
struct Edge{
	int u,v;
}edg[N];
vector<Pair> mp[N];
int deg[N];
vector<int> st;
int vis[N];
void dfs(int u,int pa){
	while(mp[u].size()){
		auto e=mp[u].back();mp[u].pop_back();
		int v=e.v,id=e.id;
		if(vis[id]) continue;
		vis[id]=1;
		dfs(v,id);
	}
	st.push_back(pa);
}
void solve(){
	int n;cin>>n;
	st.clear();
	for(int i=1;i<=2*n;i++){
		mp[i].clear();
		deg[i]=0;
		vis[i]=0;
	}
	vector<int> lsh1,lsh2;
	for(int i=1;i<=n;i++){
		int u,v;cin>>u>>v;
		lsh1.push_back(u);
		lsh2.push_back(v);
		edg[i]={u,v};
	}
	lsh1.push_back(-1);lsh2.push_back(-1);
	sort(lsh1.begin(),lsh1.end());lsh1.erase(unique(lsh1.begin(),lsh1.end()),lsh1.end());
	sort(lsh2.begin(),lsh2.end());lsh2.erase(unique(lsh2.begin(),lsh2.end()),lsh2.end());
	int tmp=lsh1.size()-1;
	for(int i=1;i<=n;i++){
		edg[i].u=lower_bound(lsh1.begin(),lsh1.end(),edg[i].u)-lsh1.begin();
		edg[i].v=lower_bound(lsh2.begin(),lsh2.end(),edg[i].v)-lsh2.begin()+tmp;
		int u=edg[i].u,v=edg[i].v;
		//cout<<u<<" "<<v<<"\n";
		mp[u].push_back({v,i});
		mp[v].push_back({u,i});
		deg[u]++;
		deg[v]++;
	}
	int m=n;n=lsh1.size()+lsh2.size()-2;
	int num=0;
	for(int i=1;i<=n;i++){
		if(deg[i]&1) num++;
	}
	//cout<<num<<"\n";
	if(num!=2&&num!=0){
		cout<<"NO\n";
		return ;
	}
	int S=-1;
	if(num==0){
		for(int i=1;i<=n;i++){
			if(mp[i].size()) S=i;
		}
	}
	else{
		for(int i=1;i<=n;i++){
			if(deg[i]&1) S=i;
		}		
	}
	//cout<<S<<"\n";
	if(S!=-1) dfs(S,0);
	reverse(st.begin(),st.end());
	if(st.size()-1!=m){
		cout<<"NO\n";
		return ;
	}
	cout<<"YES\n";
	for(auto v:st) if(v) cout<<v<<" ";cout<<"\n";
}
int main(){
	//freopen("in.txt","r",stdin);
	int t;cin>>t;
	while(t--) solve();
	return 0;
}
posted @ 2026-01-13 14:26  Ming3398  阅读(7)  评论(0)    收藏  举报