首页 > 其他分享 >CF527E Data Center Drama 题解

CF527E Data Center Drama 题解

时间:2024-05-18 15:07:45浏览次数:12  
标签:nxt head CF527E 题解 ++ tot Drama int edge

@

目录

题目

CF527E Data Center Drama · 戳这里

题意

  • 给定一张 $n$ 个点 $m$ 条边的连通无向图。
  • 你需要加尽可能少的边,然后给所有边定向,使得每一个点的出入度都是偶数。
  • 边可以是自环,也可以有重边。
  • $n \le 10^5$,$m \le 2 \times 10^5$。

(本题是 SPJ,所以顺序不用管)

题解

思路

所有顶点度数都为偶数,且该图是连通图,是无向图存在欧拉回路的充要条件。

所以我们需要将所有顶点度数为奇数的点两两相连,但是并不是所有存在欧拉回路的图都满足条件,还需要满足边数为偶数。

所以如果最后边数是奇数,随便找个点连个自环即可(这里就把 1 号节点连一个自环了)。

这显然是最少的加边方案,最后跑一个欧拉回路出来,然后隔一条边换一个方向即可。

详解

首先,存图我们用链式前向星存,然后在记录每个点的入度。

这里我们第一条边从 $2$ 开始记,因为这样我们按顺序记录正着的边和反着的边,反着的边的编号就等于正着的边的编号异或 $1$。

int edge_tot = 1;
int in_cnt[N];
int head[N];

struct Edge {
	int to;
	int nxt;
};

Edge edge[N];

void add(int u, int v) {
	++edge_tot;
	edge[edge_tot].to = v;
	edge[edge_tot].nxt = head[u];
	head[u] = edge_tot;
	++in_cnt[v];
}

接下来是主函数的输入部分。

int n, m;
int u, v;
scanf("%d%d", &n, &m);

for(int i = 1; i <= n; ++i)
  head[i] = -1;

for(int i = 1; i <= m; ++i) {
  scanf("%d%d", &u, &v);
  add(u, v);
  add(v, u);
}

然后记录一下入度为奇数的点。

我们用一个 $vector$ 来存。

vector <int> ill;

然后将所有入度为奇数的点都压进去。

for(int i = 1; i <= n; ++i)
  if(in_cnt[i] & 1)
    ill.push_back(i);

再把它们两两相连。

for(int i = 0; i < ill.size(); i += 2) {
  add(ill[i], ill[i + 1]);
  add(ill[i + 1], ill[i]);
  ++m;
}

然后判断如果这时候边数 $m$ 是奇数,就给 $1$ 号节点加个自环。

if(m & 1) {
  add(1, 1);
  ++m;
}

先输出一个边数 $m$。

printf("%d\n", m);

然后就是输出边了,这里跑个欧拉回路就行了。

bool vis[N];
int print_tot;

void dfs(int u) {
	for(int &i = head[u]; i != -1; ) {
		int v = edge[i].to;
		
		if(vis[i]) {
			i = edge[i].nxt;
			continue;
		}
		
		vis[i] = vis[i ^ 1] = true;
		
		i = edge[i].nxt;
		
		dfs(v);
		
		++print_tot;
		
		if(print_tot & 1)
			printf("%d %d\n", u, v);
		else
			printf("%d %d\n", v, u);
	}
}

注意事项

  • for(int &i = head[u]; i != -1; ) 里的 &i

  • i = edge[i].nxt; 要写两遍,不能提到前面,否则后面的 i 就都变了。

代码

#include <cstdio>
#include <vector>
using namespace std;

const int N = 1e6 + 5;

int n, m;
int u, v;
int edge_tot = 1;
int in_cnt[N];
vector <int> ill;
bool vis[N];
int print_tot;
int head[N];

struct Edge {
	int to;
	int nxt;
};

Edge edge[N];

void add(int u, int v) {
	++edge_tot;
	edge[edge_tot].to = v;
	edge[edge_tot].nxt = head[u];
	head[u] = edge_tot;
	++in_cnt[v];
}

void dfs(int u) {
	for(int &i = head[u]; i != -1; ) {
		int v = edge[i].to;
		
		if(vis[i]) {
			i = edge[i].nxt;
			continue;
		}
		
		vis[i] = vis[i ^ 1] = true;
		
		i = edge[i].nxt;
		
		dfs(v);
		
		++print_tot;
		
		if(print_tot & 1)
			printf("%d %d\n", u, v);
		else
			printf("%d %d\n", v, u);
	}
}

int main() {
	scanf("%d%d", &n, &m);
	
	for(int i = 1; i <= n; ++i)
		head[i] = -1;
	
	for(int i = 1; i <= m; ++i) {
		scanf("%d%d", &u, &v);
		add(u, v);
		add(v, u);
	}
	
	for(int i = 1; i <= n; ++i)
		if(in_cnt[i] & 1)
			ill.push_back(i);
	
	for(int i = 0; i < ill.size(); i += 2) {
		add(ill[i], ill[i + 1]);
		add(ill[i + 1], ill[i]);
		++m;
	}
	
	if(m & 1) {
		add(1, 1);
		++m;
	}
	
	printf("%d\n", m);
	
	dfs(1);
	
	return 0;
}

AC 记录

提交记录 · 戳这里

尾声

如果这篇博客对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!

最后,祝您(您的团队)在 OI 的路上一路顺风!!!

┬┴┬┴┤・ω・)ノ ByeBye

标签:nxt,head,CF527E,题解,++,tot,Drama,int,edge
From: https://www.cnblogs.com/pangyuchen75-blog/p/18199353

相关文章

  • Codeforces 769B News About Credit 题解
    题目简述波利卡普在由$n$名学生(包括他自己)组成的小组中学习,编号为$1$到$n$,波利卡普的编号始终是$1$。他们都在社交网络上注册,每个学生都有一个值$a_i$,表示第$i$名学生每天能发送的最大信息数。清晨,波利卡普知道了一个重要消息,他认为有必要通过私人消息紧急通知所有组员......
  • 安装vue/cli报错问题解决
    在管理员终端中输入命令:npmi-g@vue/cli错误原因证书已过期,需要安装淘宝镜像npmconfigsetregistryhttps://registry.npmmirror.com使用cnpm安装脚手架报错cnpmi-g@vue/cli 这个错误表明你尝试执行的 cnpm 命令无法加载,因为PowerShell策略不允许执......
  • P10125 「Daily OI Round 3」Simple 题解
    题目传送门简单模拟,主要考察字符串。首先输入一个char类型的数组,然后直接遍历每一位是否为Acoipp或Svpoll即可。//Simple//codeby:cq_irritater//time:2024/02/04#include<bits/stdc++.h>usingnamespacestd;chara[10];intmain(){//freopen("......
  • P8684 [蓝桥杯 2019 省 B] 灵能传输 题解
    题目传送门本题涉及到了\(3\)种算法:前缀和,排序以及贪心。(1)前缀和本题实际上要求通过某种灵能传输可以使得该序列的最大值最小。而由前缀和可知,当某一个前缀和序列保持有序(或前缀和序列表示的函数单调)时,其\(s[i]-s[i-1]\)的最大值可以达到最小。通过对几个样例的观察......
  • P9686 Judg. 题解
    题目传送门一道简单模拟。这道题最简单的方法就是直接在for循环中判断题目给出状态是否为AC,如果不是则输出当前\(i\)的值,否则就不输出。#include<bits/stdc++.h>usingnamespacestd;constintMAXN=1e5+10;intn;stringa[MAXN];intmain(){ scanf("%......
  • P8741 [蓝桥杯 2021 省 B] 填空问题 题解
    题目传送门试题A:空间【解析】本题考察计算机存储的基础知识,只要掌握空间存储的换算方法,就能够算出答案。【程序】#include<bits/stdc++.h>usingnamespacestd;intmain(){printf("%d\n",256*8/32*1024*1024);return0;}【答案】67108864......
  • P8679 [蓝桥杯 2019 省 B] 填空问题 题解
    题目传送门试题A:组队【解析】本题是一道经典的DFS搜索题,每次对各号位的选手进行DFS,找到各号位上有成绩的选手时再进行进一步搜索即可。【程序】#include<bits/stdc++.h>usingnamespacestd;intteam[20][6];intmax_sum;boolvis[20];voiddfs(intu,intsu......
  • P9517 drink 题解
    题目传送门这道题考场上用的查找做的。先用一个结构体分别表示firstlast,然后进行查找即可,两个for循环分别计算出first和last,最后计算它们的差值。(注意,计算差值时要加1)然后你就会发现一个问题:只有\(90\)分。所以我们来思考一下哪里出现了问题。你会发现:如果全都是......
  • Codeforces 959B Mahmoud and Ehab and the message 题解
    题目简述小A想要给他的朋友小B发送了一条有$m$个单词的消息。他们的语言由编号从$a_1$到$a_n$的$n$个单词组成。一些单词具有相同的意思,因此存在$k$个单词组,其中每个组中的所有单词具有相同的意思。小A知道第$i$个单词可以以成本$m_i$发送。对于他的每个消息......
  • Codeforces 1113B Sasha and Magnetic Machines 题解
    题目简述有一个长度为$n$的正整数序列。你可以对这个数列进行最多$1$次的如下操作:选择两个数$i$和$j$,其中$1\leqi,j\leqn$并且$i\neqj$,并选择一个可以整除$a_i$的正整数$x$,然后将$a_i$变为$\frac{a_i}{x}$,将$a_j$变为$a_j\cdotx$。问你操作后,该序......