时间限制:1000ms
单点时限:1000ms
内存限制:256MB

描述

现在有一棵有N个带权顶点的树,顶点编号为1,2,...,N。我们定义一条路径的次小(最小)权为它经过的所有顶点(包括起点和终点)中权值次小(最小)顶点的权值。现在给定常数c,你需要求出:存在多少个使得u<v的顶点组(u,v),满足从u到v的最短路的次小权恰为c但最小权不为c。
输入

第一行有两个数N和c。(1<=n<=100000)

第二行N个数,依次表示每个顶点的权值。

接下来N-1行,每行两个数,代表这棵树的一条边所连接的两个顶点的编号。

我们保证输入中的数都在int以内。
输出

一个数,为答案。
样例输入

8 2
    2 2 3 3 1 2 3 2
    1 2
    3 2
    3 8
    4 2
    5 2
    5 6
    6 7

样例输出

17


Solution

为了方便, 把我们要考虑的树记作$T=(V, E)$, 用$w[u]$表示节点$u$ ($u\in V$) 的权值.

先考虑一个简化的问题:

求最小权小于$c$且次小权不小于$c$的路径$(u, v)$的数目.

为了解决这个问题, 我们考虑如下的添边过程:

我们考虑一个动态的图$S(V, E'), E'\subseteq E$.

从$S=(V, \emptyset)$开始, 先把所有满足$w[u]\ge c \land w[v] \ge c$的边$(u, v)$加到$S$中,

然后考虑满足

\[w[u]<c \land w[v]\ge c \lor w[u]\ge c \land w[v] <c\]

的边$(u, v)$, 不失一般性, 不妨设 $w[u]<c, w[v]\ge c$.

我们先把$u$固定为$u_0$, 考虑将所有符合上述条件的边$\{(u_0, v)\}$加到$s$中将能获得多少满足条件的路径.

显然这些满足条件的路径上的最小权就是$w[u_0]$.

(未完待续...)

(无力写了, 先把代码贴上)


UPD

前面写得太罗嗦了, 结果现在自己都看不大懂了. 其实做法一句话就能说清楚:

最小权小于$c$, 次小权不小于$c$的路径数 $-$ 最小权小于$c$, 次小权大于$c$的路径数

Implementation

 #include <bits/stdc++.h>
using namespace std;
using LL=long long;
const int N{<<}; int a[N]; struct edge{
int u, v;
void read(){
cin>>u>>v;
}
}e[N]; struct DSU{
int par[N], size[N];
int n;
DSU(int n):n(n){}
void init(){
for(int i=; i<=n; i++){
par[i]=i;
size[i]=;
}
}
int find(int x){
return x==par[x]?x:par[x]=find(par[x]);
}
void unite(int x, int y){
x=find(x), y=find(y);
if(x!=y) par[x]=y, size[y]+=size[x];
}
}; vector<int> f[N]; void prep(DSU &b, int n, int c){
b.init();
for(int i=; i<=n; i++) f[i].clear();
for(int i=; i<n; i++){
int u=e[i].u, v=e[i].v;
if(a[u]>=c && a[v]>=c){
b.unite(u, v);
}
}
} int main(){
int n, c;
cin>>n>>c;
DSU b(n); for(int i=; i<=n; i++)
cin>>a[i];
for(int i=; i<n; i++)
e[i].read(); LL res=; prep(b, n, c); for(int i=; i<n; i++){
int u=e[i].u, v=e[i].v;
if(a[u]<c ^ a[v]<c){ //tricky
// cout<<u<<' '<<v<<endl;
if(a[v]<c) swap(u, v);
int rv=b.find(v);
// res+=LL(b.size[u])*LL(b.size[v]);
// if(ru!=rv)
f[u].push_back(b.size[rv]);
}
} for(int i=; i<=n; i++){
// if(f[i].size()) cout<<"#"<<i<<endl;
LL sum=, t=;
for(auto &x: f[i])
sum+=x;
for(auto &x: f[i]) t+=LL(x)*(sum-x);
res+=t>>;
res+=sum;
} prep(b, n, c+); for(int i=; i<n; i++){
int u=e[i].u, v=e[i].v;
if(a[u]<c && a[v]>c || a[u]>c && a[v]<c){ //tricky
if(a[v]<c) swap(u, v);
int rv=b.find(v);
// res+=LL(b.size[u])*LL(b.size[v]);
f[u].push_back(b.size[rv]);
}
} for(int i=; i<=n; i++){
LL sum=, t=;
for(auto &x: f[i])
sum+=x;
for(auto &x: f[i]) t+=LL(x)*(sum-x);
res-=t>>, res-=sum;
} cout<<res<<endl;
}

hihocoder #1112 树上的好路径的更多相关文章

  1. Codefroces Gym 100781A(树上最长路径)

    http://codeforces.com/gym/100781/attachments 题意:有N个点,M条边,问对两两之间的树添加一条边之后,让整棵大树最远的点对之间的距离最近,问这个最近距离是多 ...

  2. Codeforces Round #526 D - The Fair Nut and the Best Path /// 树上两点间路径花费

    题目大意: 给定一棵树 树上每个点有对应的点权 树上每条边有对应的边权 经过一个点可得到点权 经过一条边必须花费边权 即从u到v 最终得分=u的点权-u到v的边权+v的点权 求树上一条路径使得得分最大 ...

  3. 【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)

    Walking Race   Description flymouse's sister wc is very capable at sports and her favorite event is ...

  4. ●hihocoder #1394 网络流四·最小路径覆盖

    题链: http://hihocoder.com/problemset/problem/1394 题解: 有向图最小路径覆盖:最少的路径条数不重不漏的覆盖所有点. 注意到在任意一个最小路径覆盖的方案下 ...

  5. hihoCoder 1394 : 网络流四·最小路径覆盖

    题目链接:https://hihocoder.com/problemset/problem/1394 题目说是网络流,但是其实就是求有向无环图的最小路径覆盖. 不会网络流,只好用二分匹配了. 把每个点 ...

  6. hihocoder 1676 树上等差数列 黑科技树形dp

    #1676 : 树上的等差数列 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵包含N个节点的无根树,节点编号1~N.其中每个节点都具有一个权值,第i个节点的权值 ...

  7. hihocoder #1394 : 网络流四·最小路径覆盖(最小路径覆盖)

    #1394 : 网络流四·最小路径覆盖 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 国庆期间正是旅游和游玩的高峰期. 小Hi和小Ho的学习小组为了研究课题,决定趁此机 ...

  8. HDU 6043:Colorful Tree(树上统计所有路径总颜色数)***

    题目链接 题意 给出一棵有n个结点的树,每个结点有一个颜色,问在这棵树的所有路径中,每条路径的颜色数求和是多少. 思路 求每种颜色的贡献可以转化为总的和减去每种颜色在哪些路径上没有出现的贡献,一个颜色 ...

  9. SPOJ 1825 经过不超过K个黑点的树上最长路径 点分治

    每一次枚举到重心 按子树中的黑点数SORT一下 启发式合并 #include<cstdio> #include<cstring> #include<algorithm&g ...

随机推荐

  1. Atom插件安装

    Atom插件安装 Atom狂拽炫酷插件之activate-power-mode 引语: 在前文中提到了关于插件的安装,似乎简单易操作,不过最后我发现是我自己想简单了. activate-power-m ...

  2. swift——启动页国际化:一步一步动态加载启动页图片,启动的时候加载文字

    由于公司的需求,要求做一个国际化的启动页,因为app我也弄国际化了,就剩下启动页国际化未完成,百度了呵谷歌了好多答案都不尽如人意,最后也是看见同事完成,我也问了具体的做法,决定分享给需要的人,免得和我 ...

  3. Qt 5.2 Creator 和 vs2012 QT 插件的安装

    在QT官网下载QT http://qt-project.org/downloads 我下的是64位版本Qt 5.2.1 for Windows 64-bit vs2012插件是  Visual Stu ...

  4. web 前端常用组件【03】Bootstrap Multiselect

    实际的项目网站中或多或少的或用到多选框,我选用的一款是 Bootstrap Multiselect. 官方文档:http://www.kuitao8.com/demo/20140224/1/boots ...

  5. PRML读书会第十二章 Continuous Latent Variables(PCA,Principal Component Analysis,PPCA,核PCA,Autoencoder,非线性流形)

    主讲人 戴玮 (新浪微博: @戴玮_CASIA) Wilbur_中博(1954123) 20:00:49 我今天讲PRML的第十二章,连续隐变量.既然有连续隐变量,一定也有离散隐变量,那么离散隐变量是 ...

  6. C#调用百度静态地图

    来深圳一年多了,感觉深圳的IT氛围确实比长沙好,工作和生活节奏比较快,适合于学习.来深后一直在现在所在的公司,部门从开始4个人,发展到现在10来人了,感觉还是不错的. 发现自己很少写博客了,倒不是学得 ...

  7. 【jQuery EasyUI系列】使用属性介绍

    1.ValidateBox The validatebox is designed to validate the form input fields.If users enter invalid v ...

  8. Qt自定义窗体,边框,圆角窗体

    MainWindow::MainWindow(QWidget*parent): QMainWindow(parent), ui(new Ui::MainWindow) { setAttribute(Q ...

  9. Ubuntu14.04下jdk的安装

    1.下载JDK目前最新的JDK版本是:Java SE Development Kit 8u52.解压安装我们把JDK安装到这个路径:/usr/lib/jvm如果没有这个目录(第一次当然没有),我们就新 ...

  10. [转]jquery 对 Json 的各种遍历

    原文地址:http://caibaojian.com/jquery-each-json.html 概述 JSON(javascript Object Notation) 是一种轻量级的数据交换格式,采 ...