中南多校对抗赛 第三场 E

E:Eulerian Flight Tour

题意:

给你一张无向图,要你给这个图加边使得其形成一个欧拉回路

题解:

首先使得所有节点的度都为偶数,然后将这个图联通起来

对于度为奇数的点,将将他和他的父节点连接起来

连接完后如果这个图是联通的,那么就直接输出结果

如果这个图有多个联通块:

分类讨论:

如果有2个联通块,两个联通块对着连成一个环

如果有多个联通块,用一个环将这几个联通块连起来即可

代码:

# E:Eulerian Flight Tour

## 题意:

给你一张无向图,要你给这个图加边使得其形成一个欧拉回路

## 题解:

首先使得所有节点的度都为偶数,然后将这个图联通起来

对于度为奇数的点,将将他和他的父节点连接起来

连接完后如果这个图是联通的,那么就直接输出结果

如果这个图有多个联通块:

分类讨论:

如果有2个联通块,两个联通块对着连成一个环

如果有多个联通块,用一个环将这几个联通块连起来即可

代码:

```c++
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
#define FIN freopen("input.txt","r",stdin);
const int maxn = 4e3 + 5;
int n, m;
int vis[maxn];
int deg[maxn];
bool G[maxn][maxn];
bool flag;
vector<pii> ans;
void dfs(int u, int p) {
    vis[u] = 1;
    for(int v = 1; v <=n; v++) {
        if(vis[v]) continue;
        if(G[u][v]) continue;
        dfs(v, u);
    }
    if(deg[u] & 1) {
        if(p == -1) flag = false;
        else {
            ans.push_back(make_pair(u, p));
            deg[u]++, deg[p]++;
            G[u][p] = G[p][u] = 1;
        }
    }
}

vector<int> tmp;
vector<vector<int>> A;
void dfs1(int u) {
    vis[u] = 1;
    for(int v = 1; v <= n; v++) {
        if(v == u) continue;
        if(vis[v]) continue;
        if(!G[u][v]) continue;
        dfs1(v);
    }
    tmp.push_back(u);
}
int main() {
#ifndef ONLINE_JUDGE
    FIN
#endif
    cin >> n >> m;
    memset(deg,0,sizeof(deg));
    memset(G,0,sizeof(G));
    for(int i = 0, u, v; i < m; i++) {
        cin >> u >> v;
//        u--,v--;
        deg[u]++, deg[v]++;
        G[u][v] = G[v][u] = 1;
    }
//    cout<<"hhh"<<endl;
    flag = true;
    ans.clear();
    for(int i = 1; i <= n; i++) {
        if(vis[i]) continue;
        dfs(i, -1);
    }
    if(!flag) {
        cout << -1 << endl;
    } else {
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++) {
            if(vis[i]) continue;
            tmp.clear();
            dfs1(i);
            A.push_back(tmp);
        }
        if (A.size() == 2) {
            if (A[0].size() > A[1].size()) swap(A[0], A[1]);
            if (A[0].size() == 1) {
                int t = A[0][0];
                int u = -1, v=-1;
                for (int i = 0; i < A[1].size(); ++i) {
                    for(int j = i + 1; j < A[1].size(); ++j) {
                        int cu = A[1][i], cv = A[1][j];
                        if (!G[cu][cv]) u = cu, v = cv;
                    }
                }
                if (u == -1) {
                    if (ans.size() == 0) {
                        cout << -1 << endl;
                        return 0;
                    }
                    u = ans.back().first;
                    v = ans.back().second;
                    ans.pop_back();
                } else {
                    ans.push_back(make_pair(u, v));
                }
                ans.push_back(make_pair(t, u));
                ans.push_back(make_pair(t, v));
            } else {
                for (int it = 0; it < 2; ++it) {
                    for (int it2 = 0; it2 < 2; ++it2) {
                        ans.push_back(make_pair(A[0][it], A[1][it2]));
                    }
                }
            }
        } else if (A.size() > 2) {
            for (int i = 0; i < A.size(); ++i) {
                int j = (i + 1) % A.size();
                ans.push_back(make_pair(A[i][0], A[j][0]));
            }
        }
        cout << ans.size() << endl;
        for (int i = 0; i < ans.size(); i++) {
            if (ans[i].first > ans[i].second) swap(ans[i].first, ans[i].second);
            cout << ans[i].first << " " << ans[i].second  << endl;
        }
    }
    return 0;
}

```

原文地址:https://www.cnblogs.com/buerdepepeqi/p/10630195.html

时间: 2024-11-14 12:47:21

中南多校对抗赛 第三场 E的相关文章

中南多校对抗赛 第三场 B

B:Arithmetic Progressions 题意: 给你一个长度为n的序列,问你这个序列中长度最长的等差数列长度为多少 题解: 方法一:将数组从小到大排序,n方扫,枚举出公差d,然后二分找有多少个满足等差序列的值即可,emmm虽然说不知道为什么这种最差复杂度为n^3*logn的暴力能过,可能是csuoj太快了吧. 代码: #include <bits/stdc++.h> #define eps 1e-8 #define INF 0x3f3f3f3f #define PI acos(-1

【多校赛第三场】Redraw Beautiful Drawings【网络流】【谜のWA】

参考题解:http://blog.csdn.net/qian99/article/details/38276887 #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <queue> #include <vector> #include <algorithm>

多校联赛第三场(部分题解)

1001. Magician (hdu5316) 这个题目用到线段树来合并区间,题目有句话的意思A beautiful subsequence is a subsequence that all the adjacent pairs of elves in the sequence have a different parity of position说的是相邻的两个元素必须有不同的奇偶位置,所有一个序列有四种可能的形式,奇...奇, 奇...偶,偶...奇, 偶...偶,这四种形式只是端点的奇

HDU 4893 Wow! Such Sequence!(2014年多校联合 第三场 G)(线段树)

磨了一天的线段树,不能说完全搞清楚,只能说有一个大概的了解,靠着模板才把这道题A了,只能说太弱~~! 题意: 初始时有一字符串,全为0. 三种操作: 1 k d - add  把d加到第k个数上去2 l r - query sum 计算l到r所有数的和3 l r - change to nearest Fibonacci 把l到r的数修改为距离它最近的斐波那契数 节点附件三个值: s1:由lazy控制的区间的正确的和. s2:区间内与所有数相近的fib数之和,随着单点更新而更新. col:laz

HDU 5762 Teacher Bo (鸽笼原理) 2016杭电多校联合第三场

题目:传送门. 题意:平面上有n个点,问是否存在四个点 (A,B,C,D)(A<B,C<D,A≠CorB≠D)使得AB的横纵坐标差的绝对值的和等于CD的横纵坐标差的绝对值的和,n<10^5,点的坐标值m<10^5. 题解:表面上这道题复杂度是O(n^2)会超时的,而实际上这些坐标差绝对值的和最大是2*10^5,所以复杂度不是O(n^2),而是O(min(n^2,m)),这就是著名的鸽笼原理. #include <iostream> #include <cstdio

HDU 5752 Sqrt Bo (思维题) 2016杭电多校联合第三场

题目:传送门. 题意:一个很大的数n,最多开5次根号,问开几次根号可以得到1,如果5次还不能得到1就输出TAT. 题解:打表题,x1=1,x2=(x1+1)*(x1+1)-1,以此类推.x5是不超过long long的,判断输出即可. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long

hdu 5326 Work(杭电多校赛第三场)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5326 Work Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 583    Accepted Submission(s): 392 Problem Description It’s an interesting experience to

2014多校第三场1005 || HDU 4891 The Great Pan(模拟)

题目链接 题意 : 给你n行字符串,问你有多少种理解方式.有两大类的理解 (1){A|B|C|D|...}代表着理解方式可以是A,可以是B或C或者D. (2)$blah blah$,在$$这两个符号中间,如果是不连续的空格的那个位置就有2种理解方式,可以理解为没有空格也可以理解为有空格.如果有连续N个空格的位置,那里就有N+1种理解方式. 最后所有的理解方式相乘,数据保证$一定与$匹配,{一定与匹配},不会有任何嵌套,类似{$$}或者{{}}或者${}$这种情况都不会出现,也不会有{$}这种情况

hdu-4893-Wow! Such Sequence!-线段树【2014多校第三场-J】

题意:一个初始为0的数组,支持三种操作:1.向第k个数添加d,(|d| < 2^31);2.把[l, r]区间内的数字都换成与它最相近的Fibonacci数;3.询问[l, r]区间的和. 思路:初始化Fibonacci数组,longlong 类型内90个就够用了. 线段树区间查询,用lazy标记, sgt[]记录线段树各个节点的区间和, fib_num_sum[]记录与各个叶子节点当前值最接近的Fibonacci数,传递到区间fib_num_sum[]就是区间Fibonacci数的和. 操作1