题解51nod1967 路径定向

Posted twilight-sx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解51nod1967 路径定向相关的知识,希望对你有一定的参考价值。

  第一次写欧拉回路,实际上只要dfs下去就可以了,反正每条边都是要遍历一遍的……

  关键有两个性质:1.一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。2.一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。

  所以我们可以将所有的奇点之间两两连边使得它们成为偶点。此时这张图上必然存在欧拉路径,也就是所有顶点的入度等于出度,我们只需要减去奇点即可。

#include <bits/stdc++.h>
using namespace std;
#define maxn 1000000
int n, m, tot, cnt;
int e[maxn], rec[maxn], degree[maxn];

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); }
    while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar();
    return x * k;
}

struct edge
{
    int cnp, to[maxn], last[maxn], head[maxn], id[maxn], mark[maxn];
    edge() { cnp = 2; }
    void add(int u, int v)
    {
        to[cnp] = v, id[cnp] = 1, last[cnp] = head[u], head[u] = cnp ++;
        to[cnp] = u, id[cnp] = 0, last[cnp] = head[v], head[v] = cnp ++;
    }
}E1; 

void dfs(int u)
{
    for(int i = E1.head[u]; i; i = E1.last[i])
    {
        if(E1.mark[i]) continue;
        int v = E1.to[i];
        if(E1.id[i]) E1.mark[i] = E1.mark[i ^ 1] = 1;
        else E1.mark[i] = E1.mark[i ^ 1] = 2;
        dfs(v);
    }
}

int main()
{
    n = read(), m = read();
    for(int i = 1; i <= m; i ++)
    {
        int x = read(), y = read();
        degree[x] ++, degree[y] ++; E1.add(x, y);
    }
    for(int i = 1; i <= n; i ++) 
        if(degree[i] & 1) e[++ cnt] = i;
    int M = E1.cnp;
    for(int i = 1; i <= cnt; i += 2)
    {
        int x = e[i], y = e[i + 1];
        E1.add(x, y);
    }
    for(int i = 1; i <= n; i ++) dfs(i);
    printf("%d
", n - cnt);
    for(int i = 2; i < M; i += 2) 
        if(E1.mark[i] == 1) putchar(0);
        else putchar(1);
    return 0;
}

 

以上是关于题解51nod1967 路径定向的主要内容,如果未能解决你的问题,请参考以下文章

51nod1967 路径定向(欧拉回路+结论题)

[51nod1143] 路径和树

51nod1149 Pi的递推式

51 Nod 1247 可能的路径(数学)

51nod 1274 最长递增路径(DP)

Luogu P1967 货车运输题解