题解传送机
Posted kcn999
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解传送机相关的知识,希望对你有一定的参考价值。
题目大意
有一个校园有$n$个路口,$m$条双向道路($1 \leqslant n \leqslant 100000$,$1 \leqslant m \leqslant 500000$)。黄黄同学想把每条路走一次且只走一次,他有一个传送机,可以把他从一个路口穿送到任意另一个路口,他至少要传送多少次才能游遍校园。
注意:可以从任意路口开始,任意路口结束,且不一定要游遍所有路口。
题解
容易想到,对于每个点,如果度数为奇数(奇点),那必然要从这个点传送走或必须要从其他点穿送到这个点。
那么,如果有两个奇点,实际上我们只用传送一次,就是从第一个奇点传送到第二个奇点,这时,实际上我们不需要从第二个奇点传送出去了。
题目中给出注意,那就是提醒我们有多张连通图。我们把只有一个点的图忽略 ,此时有$t$张图,那么图之间要传送$t - 1$次。
根据贪心策略,对于每张连通图,我们都要从奇点开始遍历。
也就是说,对于每张连通图,我们设图内奇点数量为$c$,此时要在图内传送(不包括从一张图传送到另一张图),当$c = 0$,不需要传送;否则,传送次数为$\lfloor \fracc2 \rfloor - 1$(图内遍历从第一个奇点开始)。
#include <iostream> #include <cstdio> #include <cctype> #define MAX_N (100000 + 5) #define MAX_M (500000 + 5) using namespace std; char buf[1 << 21], * p1 = buf, * p2 = buf; int Getc() return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1== p2) ? EOF : *p1++; int n, m; int r[MAX_N]; int d[MAX_M]; // degree int g[MAX_N]; int c[MAX_N], tot; int ans; int Read() int res = 0; char ch = Getc(); while(isdigit(ch) ^ 1) ch = Getc(); while(isdigit(ch)) res = res * 10 + ch - ‘0‘, ch = Getc(); return res; int Root(int x) int R = x, tmp; while(R != r[R]) R = r[R]; while(x != r[x]) tmp = r[x], r[x] = R, x = tmp; return R; int main() n = Read(); m = Read(); if(!m) return putchar(‘0‘), 0; for(register int i = 1; i <= n; ++i) r[i] = i; int u, v; for(register int i = 1; i <= m; ++i) u = Read(); v = Read(); ++d[u]; ++d[v]; u = Root(u); v = Root(v); if(u != v) r[u] = v; for(register int i = 1; i <= n; ++i) if(d[i]) u = Root(i); if(!g[u]) g[u] = ++tot; if(d[i] & 1) ++c[g[u]]; ans = tot - 1; for(register int i = 1; i <= tot; ++i) if(c[i]) ans += (c[i] >> 1) - 1; printf("%d", ans); return 0;
以上是关于题解传送机的主要内容,如果未能解决你的问题,请参考以下文章