zoukankan      html  css  js  c++  java
  • 2018年暑假第四次周赛-图论部分题解

    2018年暑假第四次周赛-图论部分题解

    A。信我啊,这是签到题

    这题是签到题

    数据出锅,多组后来补的,后来直接删除了一整个文本。纯属意外。

    出签到题难啊,本意是一道题教会17一个模型的。说没学过不该出的是没好好看题目的第四行。
    你发现当图所有的点和与这个点直接相连(由边直接连接)的点的个数为偶数的时候,你被锤的概率降低了一点点点点点
    这句话就是无向图欧拉回路判断定理。不懂百度,解法都丢题目上了。所以只要判断是否所有点的度是偶数,在并查集维护联通即可。

    几个定理自觉记一下笔记。图是否联通是欧拉回路必备的坑点。


    下面几句话自觉记笔记。

    如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。

    1. 无向图存在欧拉回路的充要条件是,所有点的度是偶数(且图联通)。
    2. 有向图存在欧拉回路的充要条件是,所有点的入度等于出度(且图联通)。

    回路是一个点出发也要回到那个点,通路不需要回到起点。同样都要经过所有边。

    1. 无向图存在欧拉通路的充要条件是,所有点的度是偶数。允许例外,两个点度为奇数。这两个点分别是起点和终点(且图联通)。
    2. 有向图存在欧拉通路的充要条件是,所有点的入度等于出度。允许例外一个点入度比出度大一,另一个点入度比出度小一(且图联通)。

    证明自己百度或者翻《离散数学》

    扩展:欧拉回路可以找路径。算法自己找


    
    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN = 1e5 + 10;
    
    int n, m, pre[MAXN], deg[MAXN];
    
    void init() {
        for(int i = 1; i <= n; i++ ) {
            pre[i] = i;
        }
    }
    
    int findx(int x) {
        return pre[x] == x ? x : pre[x] = findx(pre[x]);
    }
    
    void join(int x, int y) {
        int fx = findx(x), fy = findx(y);
        if(fx != fy) {
            pre[fx] = fy;
        }
    }
    
    bool same(int x, int y) {
        return findx(x) == findx(y);
    }
    
    int main()
    {
    //    freopen("2.in", "r", stdin);
    //    freopen("2.out", "w", stdout);
        int u, v;
        while(~scanf("%d %d", &n, &m)) {
            init();
            memset(deg, 0, sizeof(deg));
            for(int i = 1; i <= m; i++ ) {
                scanf("%d %d", &u, &v);
                join(u, v);
                deg[u]++;
                deg[v]++;
            }
            bool ok = 1;
            int cnt = 0;
            for(int i = 1; i <= n; i++) {
                if(pre[i] == i) {
                    cnt++;
                }
                if(deg[i] % 2 != 0) {
                    ok = 0;
                    break;
                }
            }
            if(ok && cnt == 1) {
                puts("yes");
            } else {
                puts("no");
            }
        }
        return 0;
    }
    

    E。【C_W_L】的预言

    表面数论,其实是图论题。

    [gcd(a_i,a_j) * gcd(a_i+1, a_j+1)≠1 ]

    求一个最大集合满足上式。如果 (a_i) , (a_j) 符合上式。那么我们连一条边,题意就是要我们就要求该图的最大团。(一个图的点集合任意两个点之间都有边叫团)最大团等于它补图的最大独立集。

    如果 (a_i), (a_j) 符合上式。那么我们连一条边
    那么 (a_i), (a_j) 同奇,同偶的时候必定有边。那么补图一定没边。
    所以它的补图是一个二分图。我们求它的最大独立集合即可。

    二分图最大独立集,匈牙利,网络流随便来一个。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN = 555;
    typedef long long LL;
    
    int n, m, first[MAXN], sign;
    
    int links[MAXN], vis[MAXN];
    
    LL a[MAXN];
    
    struct Edge {
        int to, w, next;
    } edge[MAXN * MAXN];
    
    void init() {
        memset(first, -1, sizeof(first));
        sign = 0;
    }
    
    void add_edge(int u, int v, int w) {
        edge[sign].to = v;
        edge[sign].w = w;
        edge[sign].next = first[u];
        first[u] = sign++;
    }
    
    int dfs(int x) {
        for(int i = first[x]; ~i; i = edge[i].next) {
            int to = edge[i].to;
            if(!vis[to]) {
                vis[to] = 1;
                if(!links[to] || dfs(links[to])) {
                    links[to] = x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        while(~scanf("%d", &n)) {
            init();
            for(int i = 1; i <= n; i++ ) {
                scanf("%lld", &a[i]);
            }
            for(int i = 1; i <= n; i++ ) {
                for(int j = 1; j <= n; j++ ) {
                    if(__gcd(a[i], a[j]) == 1 && __gcd(a[i] + 1, a[j] + 1) == 1) {
                        add_edge(i, j, 1);
                    }
                }
            }
            int ans = n;
            for(int i = 1; i <= n; i++ ) {
                if(a[i] & 1) {
                    memset(vis, 0, sizeof(vis));
                    ans -= dfs(i);
                }
            }
            printf("%d
    ", ans);
        }
    
        return 0;
    }
    
  • 相关阅读:
    2018.1.10 区块链论文翻译
    2018.1.9 区块链论文翻译
    2019.1.7 区块链论文翻译
    #在蓝懿iOS学习的日子#
    #在蓝懿学习iOSd的日子#
    #在蓝懿iOS学习的日子#2014年10月15日
    #蓝懿iOSi学习的日子#2015年10月14日
    #蓝懿ios学习的日子#2015年 10月13日
    #蓝懿ios学习的日子#2015年10月12鈤
    三种读写XML的方法
  • 原文地址:https://www.cnblogs.com/Q1143316492/p/9502783.html
Copyright © 2011-2022 走看看