【欧拉回路+最小生成树】SD开车@山东2018省队一轮集训day1

PROBLEM

题目描述

作为钦钦草原最绿的男人,杨某针每天都要开车巡视钦钦草原一圈。

钦钦草原由 n 个城市组成,m 条双向道路连接着它们。经过第 i 条道路要花费的时间是\(2^i\)。

杨某针想要经过每条道路至少一次,在此基础上他想最小化他花费的时间。但作为 曾经 CTSC 的 Cu 选手,他并不能很快地计算出这个问题。所以他向你求助。

输入

输入第一行包含两个正整数n,m。

接下来m行,每行两个正整数\(a_i\),\(b_i\),表示第i条边连接点\(a_i\)和\(b_i\),它的权值为\(2^i\)。保证\(a_i\neq b_i\),不存在重边,且任意两个点之间可以互相到达。

输出

输出一行一个整数,表示答案对\(10^9\)+7取模的值。

样例输入

4 5

1 2

3 4

2 3

1 3

2 4

样例输出

70

提示

最优的路线应当为 1-2-3-4-2-3-1。

对于20%的数据,n,m≤20。

对于40%的数据,n,m≤2,000。

对于100%的数据,n≤400,000,m≤500,000。

SOLUTION

若存在一条从节点S出发的路径,恰好不重不漏地经过每条边一次(可以重复经过图中的节点),最终回到起点S,则称该路径为欧拉回路。存在欧拉回路的无向图被称为欧拉图

要经过每条道路至少一次,可以对比在欧拉回路中,每条边恰好经过一次。若最佳路线经过某一条边n+1次,可以看作在原图中加上了n次那条边。由原图G加上重复走的边得到G',G'一定是一个欧拉图,由欧拉图的性质,G'中每个点的度一定为偶数。

题目要求最小花费,也就是要加的边的权值和最小。若我分若干次去添加边,这里可以贪心假设,每次加的一个边集一定是某两个度为奇数的点的最短路径上的边,然后使得这两个点的度变为偶数。

而至于如何去求两个奇数度点的最短路,可以从边的权值上下手——第i条边的权值是\(2^i\)。用求最小生成树的Kruskal算法,我们从按编号(也就是权值)小到大枚举边,然后并查集维护,建出一棵最小生成树。因为\(2^n = 2^{n-1} + 2^{n-2} + ... + 2^1+ 2\) ,所以生成树上两点距离就是原图中两点最短距离(这里需要仔细思考)。

最后dfs遍历生成树,回溯时判断当前点的度数是否为奇数,如果是奇数,让答案再加上该点和它的父节点所连的边的权值,并更新两点的度数。

最终答案要加上原图中所有边的权值和。

CODE

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 4e5 + 5;
const int MAXE = 5e5+5;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9+7; int degree[MAXN];
int u[MAXE],v[MAXE]; struct edge{
int u,v,w,nex;
}ed[MAXN<<1]; int head[MAXN],tot; void addedge(int uu,int vv,int w){
tot++;
ed[tot].u = uu;
ed[tot].v = vv;
ed[tot].w = w;
ed[tot].nex = head[uu];
head[uu] = tot;
} int fa[MAXN]; int DjsGet(int x){
if(x==fa[x])return x;
return fa[x] = DjsGet(fa[x]);
} ll fastpow(ll a,ll n){
ll res = 1;
while(n){
if(n&1)res=res*a%MOD;
a = a*a%MOD;
n>>=1;
}
return res;
} ll ans; void dfs(int u,int p){
for(int i=head[u];i;i = ed[i].nex){
int v = ed[i].v;
if(i!=(p^1))
dfs(v,i);
}
if(degree[u]&1){
ans=(ans+fastpow(2,ed[p].w))%MOD;
degree[u]++;
degree[ed[p].u]++;
}
} int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&u[i],&v[i]);
degree[u[i]]++;
degree[v[i]]++;
}
tot++;
for(int i = 1;i<=n;i++)fa[i] = i;
for(int i=1;i<=m;i++){
int fx = DjsGet(u[i]),fy = DjsGet(v[i]);
if(fx!=fy){
fa[fx] = fy;
addedge(u[i],v[i],i);
addedge(v[i],u[i],i);
}
ans=(ans+fastpow(2,i))%MOD;
}
dfs(ed[2].u,0);
printf("%lld\n",ans);
return 0;
}

【欧拉回路+最小生成树】SD开车@山东2018省队一轮集训day1的更多相关文章

  1. LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)

    LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...

  2. SD 一轮集训 day1 carcar

    可以发现每条边只能选一次或者两次,并且最后每个点的度数(∑邻接边选的次数和)都是偶数(代表有欧拉回路). 然后根据题意列一个 n 行 m+1 列的01矩阵,每一行代表一个异或方程组(每个点的度数是偶数 ...

  3. LOJ #6060. 「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set

    有趣的思博套路题,想到了基本上加上个对线性基的理解就可以过了 首先考虑到这个把数分成两半的分别异或的过程不会改变某一位上\(1\)的总个数 因此我们求出所有数的\(\operatorname{xor} ...

  4. LOJ.6060.[2017山东一轮集训Day1/SDWC2018Day1]Set(线性基)

    LOJ BZOJ 明明做过一道(最初思路)比较类似的题啊,怎么还是一点思路没有. 记所有元素的异或和为\(s\),那么\(x_1+x_2=x_1+x_1\ ^{\wedge}s\). \(s\)是确定 ...

  5. 【LOJ6060】【2017 山东一轮集训 Day1 / SDWC2018 Day1】Set 线性基

    题目大意 给出 \(n\) 个非负整数,将数划分成两个集合,记为一号集合和二号集合.\(x_1\) 为一号集合中所有数的异或和,\(x_2\) 为二号集合中所有数的异或和.在最大化 \(x_1 + x ...

  6. loj6102 「2017 山东二轮集训 Day1」第三题

    传送门:https://loj.ac/problem/6102 [题解] 贴一份zyz在知乎的回答吧 https://www.zhihu.com/question/61218881 其实是经典问题 # ...

  7. 【LOJ6060】「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基)

    点此看题面 大致题意: 让你把\(n\)个数分成两部分,使得在两部分异或和之和最大的前提下,两个异或和中较小的那个尽量小.输出最优的较小异或和. 线性基 关于线性基,可以看一下这篇博客:线性基入门. ...

  8. loj6100 「2017 山东二轮集训 Day1」第一题

    传送门:https://loj.ac/problem/6100 [题解] 我们考虑维护从某个端点开始的最长满足条件的长度,如果知道了这个东西显然我们可以用主席树来对每个节点建棵关于右端点的权值线段树, ...

  9. SD 一轮集训 day1 lose

    神TM有是结论题,我讨厌结论题mmp. 杨氏矩阵了解一下(建议去维基百科). 反正就是推柿子,使劲推,最后写起来有一点小麻烦,但是在草稿纸(然鹅我木有啊)上思路清晰的话还是没问题的. #include ...

随机推荐

  1. cookie小栗子-实现简单的身份验证

    关于Cookie Cookie是一种能够让网站Web服务器把少量数据储存到客户端的硬盘或内存里,或是从客户端的硬盘里读取数据的一种技术. 用来保存客户浏览器请求服务器页面的请求信息,可以在HTTP返回 ...

  2. [再寄小读者之数学篇](2014-06-22 积分不等式 [中国科学技术大学2012年高等数学B考研试题])

    函数 $f(x)$ 在 $[0,1]$ 上单调减, 证明: 对于任何 $\al\in (0,1)$, $$\bex \int_0^\al f(x)\rd x\geq \al \int_0^1 f(x) ...

  3. shell ip变量加法运算

    #!/bin/bash for ip in `cat a.txt`;do a=`echo $ip|awk -F '.' '{print $1}'` b=`echo $ip|awk -F '.' '{p ...

  4. java对象在内存中的结构

    在HotspotJVM中,32位机器下,Integer对象的大小是int的几倍? 我们都知道在java语言规范已经规定了int的大小是4个字节,那么Integer对象的大小是多少呢?要知道一个对象的大 ...

  5. (三)Java工程化--Git起步

    GIT学习参考:https://git-scm.com/book/zh/v2 版本控制 版本控制记录了一个或若干文件的历史变化,便于今后查阅,恢复. 三类版本控制系统 本地版本控制系统 RCS : 本 ...

  6. android:shape 设置圆形

    组件高度和宽度设置为相同的值即可<?xml version="1.0" encoding="utf-8"?><shape xmlns:andr ...

  7. Lua中的协同程序

    [前言] 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.从概念上讲,线程与协同程序的主要区别在于,一个具有多个线程的 ...

  8. shim和polyfill

    shim是将新的api引入旧的环境 polyfill是一段代码或插件 https://www.aliyun.com/jiaocheng/773254.html 理解得不够透彻...

  9. Restful风格

    今天看到一个比较好的文章,记录一下: Restful风格API中用put还是post做新增操作有什么区别? 1 HTTP协议详解 HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层 ...

  10. 【MySql】update用法

    update 语句可用来修改表中的数据, 简单来说基本的使用形式为: update 表名称 set 列名称=新值 where 更新条件; 以下是在表 students 中的实例: 将 id 为 5 的 ...