◇例题·II◇ Berland and the Shortest Paths

题目来源:Codeforce 1005F +传送门+


◆ 简单题意

给定一个n个点、m条边的无向图。保证图是连通的,且m≥n-1。

以首都(1节点)为根节点生成最小树。树的值定义为每个节点的深度和(根节点深度0)。举个例子:

而我们知道,可能有多种情况使树的权值最小,题目给出了一个整数k,如果最小树的生成方案数为ans,当 ans≤k 时,将 ans 种方案全部输出;当 ans>k 时,任意输出 k 种不同生成方案即可。输出方案格式为一个01串,第i个字符如果为0,表示不选第i条边(按照输入顺序),1为选择第i条边。


◆ 解析

其实点 i 的深度 dep[i] 就是根节点1到 i 的路径,而我们知道 1 到 i 没有任何一条路径短于它们的最短路径,所以生成树的权值最小时,根节点到每个点的距离就是原图中根节点到每个节点的最短路径。也就是说,我们生成的最小树就是一个最短路径树。然而显然有时候存在多条最短路径,这也就造成了我们生成的最小树有多种解。于是我们假装生成一棵树,实际上只是生成一个图。

由于这道题的边权都是等价的(不如就把边权看成1吧),我们可以用BFS直接求得最短路,所以说其实这也是一个BFS序图。为了考虑每种情况,我们把所有最小的BFS序边连上。下面再举一个生成BFS序图的例子(希望入门reader可以理解):

这样我们就生成了一个BFS序有根图,由于我们要生成树,而树的每一个节点的父节点少于一个。在上图中,4的父节点有两个,因此需要断开一条边——两条边是等价的,断掉任意一条即可。

我们可以把 u→v 的边存入v的边集 min_edg[v] ,那么最小权值树则是对于每一个除根节点之外的 v,选择 min_edg[v] 中的任意一条边,所以方案总数为 (除去根节点 i:2~n)min_edg[v]的边数之积。最后再DFS递归求方案即可(具体见代码)。


◆ 源代码

 /*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int MAXN=int(2e5);
const int INF=int(1e9);
int n_pnt,n_edg,k;
int dis[MAXN+];
vector<pair<int,int> > lnk[MAXN+];
vector<pair<int,int> > min_edg[MAXN+];
void BFS(int start)
{
fill(dis,dis+MAXN+,INF);
dis[start]=;
queue<int> que;
que.push(start);
while(!que.empty())
{
int u=que.front();que.pop();
for(int i=;i<lnk[u].size();i++)
{
int v=lnk[u][i].first,id=lnk[u][i].second,Stp=dis[u]+;
if(Stp>dis[v]) continue;
min_edg[v].push_back(make_pair(u,id));
if(Stp!=dis[v])
dis[v]=Stp,que.push(v);
}
}
}
bool chose[MAXN+];int cnt;
void DFS(int v)
{
if(v==n_pnt+)
{
cnt++;
for(int i=;i<=n_edg;i++)
printf("%d",chose[i]);
printf("\n");
return;
}
for(int i=;i<min_edg[v].size();i++)
{
chose[min_edg[v][i].second]=true;
DFS(v+);
chose[min_edg[v][i].second]=false;
if(cnt==k) return;
}
}
int main()
{
scanf("%d%d%d",&n_pnt,&n_edg,&k);
for(int i=,u,v;i<n_edg;i++)
scanf("%d%d",&u,&v),
lnk[u].push_back(make_pair(v,i+)),
lnk[v].push_back(make_pair(u,i+));
BFS();
long long ans=;
for(int i=;i<=n_pnt;i++)
{
ans*=min_edg[i].size();
if(ans>k) break;
}
printf("%lld\n",min(k*1ll,ans));
DFS();
return ;
}

The End

Thanks for reading!

- Lucky_Glass

(Tab:如果我有没讲清楚的地方可以直接在邮箱lucky_glass@foxmail.com email我,在周末我会尽量解答并完善博客~)

【例题收藏】◇例题·II◇ Berland and the Shortest Paths的更多相关文章

  1. Codeforces 1005 F - Berland and the Shortest Paths

    F - Berland and the Shortest Paths 思路: bfs+dfs 首先,bfs找出1到其他点的最短路径大小dis[i] 然后对于2...n中的每个节点u,找到它所能改变的所 ...

  2. Codeforces Round #496 (Div. 3) F - Berland and the Shortest Paths

    F - Berland and the Shortest Paths 思路:还是很好想的,处理出来最短路径图,然后搜k个就好啦. #include<bits/stdc++.h> #defi ...

  3. [Codeforces 1005F]Berland and the Shortest Paths(最短路树+dfs)

    [Codeforces 1005F]Berland and the Shortest Paths(最短路树+dfs) 题面 题意:给你一个无向图,1为起点,求生成树让起点到其他个点的距离最小,距离最小 ...

  4. Berland and the Shortest Paths CodeForces - 1005F(最短路树)

    最短路树就是用bfs走一遍就可以了 d[v] = d[u] + 1 表示v是u的前驱边 然后遍历每个结点 存下它的前驱边 再用dfs遍历每个结点 依次取每个结点的某个前驱边即可 #include &l ...

  5. CF1005F Berland and the Shortest Paths

    \(\color{#0066ff}{ 题目描述 }\) 一个无向图(边权为1),输出一下选边的方案使\(\sum d_i\)最小(\(d_i\)为从1到i的最短路) 输出一个方案数和方案(方案数超过k ...

  6. CF1005F Berland and the Shortest Paths (树上构造最短路树)

    题目大意:给你一个边权为$1$的无向图,构造出所有$1$为根的最短路树并输出 性质:单源最短路树上每个点到根的路径 ,一定是这个点到根的最短路之一 边权为$1$,$bfs$出单源最短路,然后构建最短路 ...

  7. CF1005F Berland and the Shortest Paths 最短路树计数

    问题描述 LG-CF1005F 题解 由题面显然可得,所求即最短路树. 所以跑出最短路树,计数,输出方案即可. \(\mathrm{Code}\) #include<bits/stdc++.h& ...

  8. [CF1005F]Berland and the Shortest Paths_最短路树_堆优化dij

    Berland and the Shortest Paths 题目链接:https://www.codeforces.com/contest/1005/problem/F 数据范围:略. 题解: 太鬼 ...

  9. Shortest Paths

    最短路径 APIs 带权有向图中的最短路径,这节讨论从源点(s)到图中其它点的最短路径(single source). Weighted Directed Edge API 需要新的数据类型来表示带权 ...

随机推荐

  1. LeetCode 860.柠檬水找零(C++)

    在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10 美元或 20 美元.你必须给 ...

  2. TP扩展Xxtea.class.php加密解密函数用法

    http://www.coolcode.org/?action=show&id=128这里可以查到一个相关文章. 附上xiunobbs里的代码,自己加了点注释,欢迎大牛批评指正 //将数值数组 ...

  3. 如何使用rem单位

    最近搞移动端,真是被rem.em与px的换算要了老命了,看了不少文档,似乎弄明白了,这不今天用又蒙圈了. 好多文档上老是说用rem就给html设置font-size,用em就给body设置font-s ...

  4. Ubuntu15.10下安装Docker

    1.首先查看linux系统版本 head -n 1 /etc/issue 2.升级包管理器 sudo apt-get update sudo apt-get install apt-transport ...

  5. JavaScript判断变量类型

    使用JavaScript变量时是无法判断出一个变量是0 还是“”的 这时可用typeof()来判断变量是string 还是number来区分0和“”, typeof(undefined) == 'un ...

  6. Swift-取消传统For循环

    1.取消传统的For循环 传统的for,在swift 3.0 被取消 i++/++i在swift 3.0 被取消 i += 1代替 for var i = 0;i<10;i +=1 { } 2. ...

  7. 微信小程序入门开发文档

    第一步:下载微信小程序开发者工具并安装,下载路径: https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 进到下载界面后,根 ...

  8. 从零开始的全栈工程师——js篇2.21(事件对象 arguments 阻止事件默认行为兼容 事件委托 事件源对象)

    一.事件对象 1.常用的事件2.每个元素身上的事件都是天生存在的 不需要我们去定义 只需要我们给这个事件绑定一个方法 当事件触发的时候就会执行这个方法 3.事件绑定的写法 ①div.onclick=f ...

  9. 仿真DDR3 Controller IP

    一.Creat a new project,generate a new DDR3 IP,Close Project. 二.打开工程文件下的 X_example_design-->simulat ...

  10. 线程队列queue

    队列queue 队列用于线程之间安全的信息交换 队列和列表的区别:队列里的信息get()后就没了,而列表获取数据则是copy,原列表里的值还在 使用前先实例化队列 q = queue.Queue(ma ...