码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】传送机

时间:2019-07-31 13:21:19      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:nbsp   getc   就是   play   fine   using   ret   gis   div   

题目大意

         有一个校园有$n$个路口,$m$条双向道路($1 \leqslant n \leqslant 100000$,$1 \leqslant m \leqslant 500000$)。黄黄同学想把每条路走一次且只走一次,他有一个传送机,可以把他从一个路口穿送到任意另一个路口,他至少要传送多少次才能游遍校园。

         注意:可以从任意路口开始,任意路口结束,且不一定要游遍所有路口。

 

题解

         容易想到,对于每个点,如果度数为奇数(奇点),那必然要从这个点传送走或必须要从其他点穿送到这个点。

         那么,如果有两个奇点,实际上我们只用传送一次,就是从第一个奇点传送到第二个奇点,这时,实际上我们不需要从第二个奇点传送出去了。

         题目中给出注意,那就是提醒我们有多张连通图。我们把只有一个点的图忽略 ,此时有$t$张图,那么图之间要传送$t - 1$次。

         根据贪心策略,对于每张连通图,我们都要从奇点开始遍历。

         也就是说,对于每张连通图,我们设图内奇点数量为$c$,此时要在图内传送(不包括从一张图传送到另一张图),当$c = 0$,不需要传送;否则,传送次数为$\lfloor \frac{c}{2} \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;
}
参考程序

 

【题解】传送机

标签:nbsp   getc   就是   play   fine   using   ret   gis   div   

原文地址:https://www.cnblogs.com/kcn999/p/11275509.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!