zoukankan      html  css  js  c++  java
  • 【题解】Weird journey Codeforces 788B 欧拉路

    传送门:http://codeforces.com/contest/788/problem/B

    好题!好题!

    首先图不连通的时候肯定答案是0,我们下面讨论图联通的情况

    首先考虑,如果我们每条边都经过两边,那么肯定是可行的

    因为这样相当于把每条边复制一遍,然后问图中是否存在欧拉路径

    既然每条边都出现了两遍,那么所有点的度数一定都是偶数,所以肯定有欧拉路径

    现在考虑将某两条边变成出现一遍,这样的话可能会有一些点的度数变成奇数

    如果我们把两条非自环的边变成出现一遍,并且这两条边不交于同一个点,那么就会有四个度数为奇数的点,则图中不存在欧拉路径

    如果我们把两条非自环的边变成出现一遍,并且这两条边交于同一个点,那么就会有两个度数为奇数的点,存在欧拉路径

    如果我们把两条自环边变成出现一遍,所有点的度数仍然为偶数,存在欧拉路径

    如果我们把一条自环,一条非自环的边变成出现一遍,那么就会有两个度数为奇数的点,存在欧拉路径

    所以一共就几种情况,除去判联通的部分,我们只要记录每个点的度数(不含自环)和自环的数量就好了

    因为题目中保证一条边不会出现两遍,所以我们的方法才是可行的

    代码:

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 const int MAXN = 1000010;
     6 
     7 int n, m;
     8 
     9 namespace Graph {
    10     int head[MAXN], nxt[MAXN<<1], to[MAXN<<1], eidx;
    11     void init() {
    12         eidx = 0;
    13         memset( head, -1, sizeof(head) );
    14     }
    15     void adde( int u, int v ) {
    16         to[eidx] = v, nxt[eidx] = head[u], head[u] = eidx++;
    17     }
    18 }
    19 
    20 bool ing[MAXN] = {0}, vis[MAXN] = {0}; // ing表示这个点是否存在于图中,因为题目只要求边互相联通,所以对于没有度数的点可以看做不存在
    21 queue<int> q;
    22 bool bfs() { // bfs判联通
    23     using namespace Graph;
    24     for( int i = 1; i <= n; ++i )
    25         if( ing[i] ) {
    26             q.push(i), vis[i] = true;
    27             break;
    28         }
    29     while( !q.empty() ) {
    30         int u = q.front(); q.pop();
    31         for( int i = head[u]; ~i; i = nxt[i] ) {
    32             int v = to[i];
    33             if( vis[v] ) continue;
    34             q.push(v), vis[v] = true;
    35         }
    36     }
    37     for( int i = 1; i <= n; ++i )
    38         if( ing[i] && !vis[i] )
    39             return false;
    40     return true;
    41 }
    42 
    43 int deg[MAXN] = {0}, loop = 0; // 每个点的度数(不含自环)和总的自环数量
    44 int main() {
    45     scanf( "%d%d", &n, &m );
    46     Graph::init();
    47     for( int i = 0; i < m; ++i ) {
    48         int u, v; scanf( "%d%d", &u, &v );
    49         ing[u] = ing[v] = true;
    50         if( u != v ) {
    51             Graph::adde(u,v), ++deg[u];
    52             Graph::adde(v,u), ++deg[v];
    53         } else { // 自环
    54             Graph::adde(u,v), ++loop;
    55         }
    56     }
    57     if( !bfs() || m < 2 ) {
    58         puts("0");
    59         return 0;
    60     }
    61     ll ans = (ll)loop*(m-loop) + (ll)loop*(loop-1)/2; // 选一个自环和一个非自环,或者选两个自环
    62     for( int i = 1; i <= n; ++i )
    63         ans += (ll)deg[i]*(deg[i] - 1)/2; // 选两个非自环,且交于同一点的边
    64     cout << ans << endl;
    65     return 0;
    66 }
  • 相关阅读:
    消息队列设计
    抓包工具Fiddler
    分布式系统和CAP
    Topshelf组件
    Parallel.For
    MVC插件
    Azure Messaging-ServiceBus Messaging
    MVC
    requireJS
    第一次react-native项目实践要点总结 good
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/6645725.html
Copyright © 2011-2022 走看看