zoukankan      html  css  js  c++  java
  • GHOJ 1017 传送机

    题目大意

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

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

    题解

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

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

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

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

             也就是说,对于每张连通图,我们设图内奇点数量为$c$,此时要在图内传送(不包括从一张图传送到另一张图),当$c = 0$,不需要传送;否则,传送次数为$lfloor frac{c}{2} floor - 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;
    }
    参考程序
  • 相关阅读:
    layui timeline使用
    Java随机数使用
    Matlab信号处理工具箱函数
    高斯白噪声(white Gaussian noise,WGN)
    概率分布之间的距离度量以及python实现
    Wasserstein距离 和 Lipschitz连续
    线性分式变换(linear fractional transformation)
    算法的时间复杂度和空间复杂度-总结
    随机森林(Random Forest,简称RF)
    增强学习与马尔科夫决策过程
  • 原文地址:https://www.cnblogs.com/kcn999/p/11275509.html
Copyright © 2011-2022 走看看