Hdu-3018 problem solving Report

Brief introduction

Given n nodes and m edges, ask how many paths are needed to pass all the m edges and each edge passes only once

Analysis

This problem is actually the second theorem in a stroke problem: if a connected undirected graph G has 2k odd vertices, then it can be drawn in k strokes, and at least in k strokes
See Wikipedia for proof: zh.wikipedia.org/wiki / one stroke problem one stroke theorem
It should be noted that in this problem, he only cares about whether he can traverse the m-edge instead of traversing all the N-nodes, so when the number of edges is 0, we should output 0; if we change the meaning of the question to at least how many paths are needed to traverse all the N-nodes, we need to consider that one or several of the N-nodes form a single connection block condition

Realization

To record which elements of each connection block have multiple implementation methods, I use weighted and check set. Create an array of vectors. The value in initialization is itself. When there is an edge between two nodes, first determine whether the two nodes belong to the same set. If not, merge them. Change the x's representative element to y and add all the elements in the vector of x to the vector of Y. After repeating the above operation M times (because there are M edges), all elements of the set are stored in the vector where the representative element of each set is located. In this case, we can directly apply theorem 2 of stroke theorem

Reference code

The reference code is for reference only. Please implement the code independently first

#include<stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;

#define N 110000

int vis[N], pa[N], d[N], used[N];
vector<int> vec[N];

void init(int n) {
    for (int i = 0; i <= n; ++i) pa[i] = i;
    memset(vis, 0, sizeof(vis));
    memset(d, 0, sizeof(d));
    memset(used, 0, sizeof(used));
    for (int i = 0; i <= n; ++i) vec[i].clear();
    for (int i = 0; i <= n; ++i) vec[i].push_back(i);
}

int findset(int x) {
    return pa[x] == x ? x : pa[x] = findset(pa[x]);
}

int main() {
    int n, m;
    while (scanf("%d%d",&n,&m) == 2) {
        init(n);

        while (m--) {
            int u, v;
            scanf("%d%d",&u, &v);
            d[u]++; d[v]++;
            used[u] = used[v] = 1;
            int x = findset(u);
            int y = findset(v);
            if (x != y) {  //union
                pa[x] = y;
                for (int i = 0; i < vec[x].size(); ++i) {
                    vec[y].push_back(vec[x][i]);
                }
            }
        }

        int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            if (!used[i]) continue;  //Ignore it if there is no edge
            int x = findset(i);
            if (!vis[x]) {
                int v = 0;
                for (int j = 0; j < vec[x].size(); ++j) {
                    int deg = d[vec[x][j]];
                    if (deg & 1) v++;
                }
                cnt += (v == 0 ? 1 : v / 2);
                vis[x] = 1;
            }
        }

        printf("%d\n",cnt);
    }
    return 0;
}

Posted by Nik on Sat, 07 Mar 2020 08:49:36 -0800