列表

详情


NC50420. 欧拉回路

描述

有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。
一共两个子任务:
  1. 这张图是无向图。(50分)
  2. 这张图是有向图。(50分)

输入描述

第一行一个整数t,表示子任务编号。,如果t=1则表示处理无向图的情况,如果t=2则表示处理有向图的情况。
第二行两个整数n,m,表示图的结点数和边数。
接下来m行中,第i行两个整数v_i,u_i,表示第i条边(从1开始编号)。保证
1.如果t=1则表示v_iu_i有一条无向边。
2.如果t=2则表示v_iu_i有一条有向边。
图中可能有重边也可能有自环。

输出描述

如果不可以一笔画,输出一行NO。
否则,输出一行YES,接下来一行输出一组方案。
1.如果t=1,输出m个整数。令,那么e表示经过的第i条边的编号。如果p_i为正数表示从v_e走到u_e,否则表示从u_e走到v_e
2.如果t=2,输出m个整数。其中p_i表示经过的第i条边的编号。

示例1

输入:

1
3 3
1 2
2 3
1 3

输出:

YES
1 2 -3

示例2

输入:

2
5 6
2 3
2 5
3 4
1 2
4 2
5 1

输出:

YES
4 1 3 5 2 6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 83ms, 内存消耗: 15896K, 提交时间: 2020-08-07 20:26:15

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10, M = 2e5 + 10;
struct edge {
	int to, next;
}e[M * 2];
int head[N], idx;
bool st[M * 2];
int din[N], dout[N], type, n, m;
vector<int> res;
int cnt;

void add(int u, int v) {
	e[idx] = {v, head[u]};
	head[u] = idx++;
}

bool check() {
	if(type == 1) {
		for(int i = 1; i <= n; i++) {
			if(din[i] + dout[i] & 1) return false;
		}
	}
	else {
		for(int i = 1; i <= n; i++) {
			if(din[i] != dout[i]) return false;
		}
	}
	return true;
}

void dfs(int u) {
	for(int &i = head[u]; ~i;) {
		if(st[i]) {
            i = e[i].next;
            continue;
        }
		st[i] = true;
		if(type == 1) st[i ^ 1] = true;
		int x;
		if(type == 1) {
			x  = i / 2 + 1;
			if(i & 1) x = -x;
		}
		else x = i + 1;
		int v = e[i].to;
        i = e[i].next;
        dfs(v);
		res.push_back(x);
	}
}

void solve() {
	memset(head, -1, sizeof head);
	scanf("%d", &type);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		add(u, v);
		dout[u]++; din[v]++;
		if(type == 1) {
			add(v, u);
		}
	}
	if(!check()) {
		puts("NO");
		return;
	}
	for(int i = 1; i <= n; i++) {
		if(head[i] != -1) {
			dfs(i);
			break;
		}
	}
	if(res.size() != m) puts("NO");
	else {
		puts("YES");
		for(int i = res.size() - 1; i >= 0; i--) {
			printf("%d ", res[i]);
		}
	}
}

int main() {
	// freopen("in.txt", "r", stdin);
	solve();
	return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 103ms, 内存消耗: 19784K, 提交时间: 2022-10-03 10:29:07

#include<bits/stdc++.h>

using namespace std;
const int N=100010,M=400010;

int n,m,type;
int h[N],e[M],ne[M],idx;
int din[N],dout[N];
bool used[M];
vector<int> res;

void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
	din[b]++,dout[a]++;
}

void dfs(int u){
	for(int &i=h[u];~i;){
		if(used[i]){
			i=ne[i];
			continue;
		}
		used[i]=true;
		if(type==1)used[i^1]=true;//删反边 
		int t;//边编号
		if(type==1){
			t=i/2+1;
			if(i&1)t=-t; 
		}
		else t=i+1;
		int j=e[i];
		i=ne[i];
		dfs(j);
		res.push_back(t);
	}
}

int main(){
	scanf("%d%d%d",&type,&n,&m);
	memset(h,-1,sizeof h);
	for(int i=1;i<=m;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		add(a,b);
		if(type==1)add(b,a);
		din[b]++,dout[a]++;
	}
	if(type==1){
		for(int i=1;i<=n;i++){
			if((din[i]+dout[i])&1){
				puts("NO");
				return 0;
			}
		}
	}
	else{
		for(int i=1;i<=n;i++){
			if(din[i]!=dout[i]){
				puts("NO");
				return 0;
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(~h[i]){
			dfs(i);
			break;
		}
	}
	if(res.size()<m)puts("NO");
	else{
		puts("YES");
		for(int i=res.size()-1;i>=0;i--)printf("%d ",res[i]);
		printf("\n");
	}
	return 0;
}

上一题