zoukankan      html  css  js  c++  java
  • HDU 3018 Ant Trip(一笔画问题)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3018

    题意:每条边过且只过一次,问至少要画几笔才能全部边都经过。。孤立的点忽视。

    分析:首先,你用笔来画的话,只可能有2种,一:每回路,a——>b  二:形成回路,a——>...——>a

    对于图中的每一块,度数数为奇数的点必须是由第一种画出来的,所以奇数/2就是画的笔数

    由两种结合而成的图,也只是奇数/2

    特别的,如果图只有第二种的话,即该块中不存在奇数点,则只要画一笔

    对于整副图(每一块块组合而成),等于 :第一块奇数点/2+第二块奇数点/2+.......,最后得,图的总奇数点/2

    接着还要计算有多少块里不存在奇数点(不存在奇数点的那块中,一定没有第一种画法,只需要画一笔),累加起来就得到答案了。。。

    代码:

    #include <iostream>
    using namespace std;
    
    const int M = 100000 + 10;
    
    int gree[M];
    int father[M];
    int rank1[M];
    int save[M];
    bool used[M];
    bool mark[M];
    
    void Make_Set(int x)
    {
        father[x] = x;
        rank1[x] = 0;
    }
    
    int Find(int x)
    {
        int k = 0;
        while (x != father[x])
        {
            save[k++] = x;
            x = father[x];
        }
    
        for (int j = 0; j < k; j++)
        {
            father[save[j]] = x;
        }
        return x;
    }
    
    
    void Union(int a, int b)
    {
    
        int x = Find(a);
        int y = Find(b);
        
        if (x == y)
        {
            return;
        }
        if (rank1[x] < rank1[y])
        {
            father[x] = y;
        }
        else
        {
            father[y] = x;
            if (rank1[x] == rank1[y])
            {
                rank1[x]++;
            }
        }
    }
    
    
    
    int main()
    {
        int n, m;
        while (~scanf("%d%d", &n, &m))
        {
    
            memset(gree, 0, sizeof(gree));
            memset(used, 0, sizeof(used));
            memset(mark, 0, sizeof(mark));
            while (m--)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                if (!used[a])
                {
                    used[a] = 1;
                    Make_Set(a);
                }
                if (!used[b])
                {
                    used[b] = 1;
                    Make_Set(b);
                }
                gree[a]++;
                gree[b]++;
                Union(a, b);
            }
    
            int ans = 0;
            for (int i = 1; i <= n; i++)
            {
                if (used[i] && gree[i] % 2 == 1)
                {    
                    if (mark[Find(i)] == 0)
                    {
                        mark[Find(i)] = 1;//标记该块已经有奇数点了
                    }
                    ans++;//计算总奇数点
                }
            }
            ans /= 2;
    
            //累加,看有多少块没奇数点。。。mark[老大] == 0没有奇数点
            for (int i = 1; i <= n; i++)
            {
                if (used[i] && father[i] == i && mark[i] == 0)
                {
                    ans++;
                }
            }
    
            printf("%d\n", ans);
        }
        return 0;
    }
  • 相关阅读:
    Vector Dictionary HashMap
    崩溃java (打印当前类的地址)
    colspan、rowspan的使用
    基础操作
    安装vuex-devtools插件
    在使用Vuex插件进行状态管理的步骤
    运行cnpm run dev出现错误解决办法
    在使用vue开发时,文件路径的引用(给文件起别名)
    下载脚手架vue.cli出现的问题
    什么是闭包?
  • 原文地址:https://www.cnblogs.com/qiufeihai/p/2657350.html
Copyright © 2011-2022 走看看