test


T1

样例输入


样例输出


答案选择u,v作为关键点

暴力的话k^2枚举跑最短路,寻找最小值就行了

50pts

考虑优化枚举量

因为答案的两个点是不同的点,所以编号的二进制表示中至少一位不同

枚举二进制每一位

假设枚举到第i位,把这一位是1的设为源点,0的设为汇点,跑多源多汇最短路

这两个集合既可以是1~n,也可以是1~k

显然1~k更优一些

建一个超级源点,向所有第一集合的点连长度为0的边

超级汇点同理

跑超级源点到超级汇点的最短路

跑32次得到最优解

#include <queue>
#include <cstdio>
#include <cstring> template <class cls>
inline cls min(const cls & a, const cls & b) {
return a < b ? a : b;
} const int mxn = ;
const int mxm = ;
const int inf = 0x3f3f3f3f; int n, m, k; int points[mxn]; int tot;
int hd[mxn];
int nt[mxm];
int to[mxm];
int vl[mxm]; inline void add_edge(int u, int v, int w) {
nt[++tot] = hd[u];
to[tot] = v;
vl[tot] = w;
hd[u] = tot;
} int dis[mxn]; struct data {
int u, d; data(int _u, int _d) :
u(_u), d(_d) {} bool operator < (const data & that) const {
return d > that.d;
}
}; std::priority_queue<data> heap; int main() {
int cas;
scanf("%d", &cas);
for (int c = ; c < cas; ++c) {
scanf("%d%d%d", &n, &m, &k);
memset(hd, , sizeof(int) * (n + )); tot = ;
for (int i = , u, v, w; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
add_edge(v, u, w);
}
for (int i = ; i < k; ++i)
scanf("%d", points + i);
int ans = inf;
for (int i = ; i < k; i <<= ) {
memset(dis, inf, sizeof(int) * (n + ));
for (int j = , p; j < k; ++j)
if (p = points[j], (j & i) == )
heap.push(data(p, dis[p] = ));
while (!heap.empty()) {
int u = heap.top().u;
int d = heap.top().d;
heap.pop();
if (dis[u] != d)
continue;
for (int e = hd[u], v, w; e; e = nt[e])
if (v = to[e], w = vl[e], dis[v] > d + w)
heap.push(data(v, dis[v] = d + w));
}
for (int j = , p; j < k; ++j)
if (p = points[j], (j & i) != )
ans = min(ans, dis[p]);
}
printf("%d\n", ans == inf ? - : ans);
}
return ;
}

T2



建反向边,tarjan然后拓扑就行了

我的思路是tarjan缩点,一个强连通分量的初始ans就是这个强连通分量里面点的最大值。然后建立新图,找到入度为0的点开始dfs,然后更新强连通分量的ans。

询问点就是找点所在的强连通分量,输出强连通分量的ans就ok



先树剖

支持单点修改,查询区间内值为x的数

如何在序列内实现

如果x比较少,完全可以建几棵线段树来实现

每次修改就是在一棵线段树内-1,另一棵+1

多了怎么办?

暴力:开100个树状数组,和刚才没什么区别

如果线段树

在每一个节点上维护一个100的数组

合并的时候可以直接暴力统计节点次数,这样代价是区间长度

如果每一位枚举则是n*100

每一层访问的点是n的,一共log层

onlogn

离线操作

-1和+1分别隶属于x和y棵线段树

把操作分类,每一次处理每一棵的线段树

有多少个颜色就有多少棵

所有操作次数相加就是2m

所以操作还是o(m)

另一种不用树剖的方法

把节点按照DFS序排下来,一个点修改的时候会对他所有子树产生影响

查询的时候 (a-->root)+(b-->root)-(lca(a,b)-->root)+(lca(a,b))

开100个树状数组

随机推荐

  1. 偶遇com组件 .rc 文件 not found .tlb文件问题:

    好久木有弄com组件来,记忆已经模糊了,今天遇见一个编译问题,折腾了半天,mark一下: xxx_x64.rc(273): error RC2135: file not found: xxx.tlb ...

  2. 搜索 问题 D: 神奇密码锁

    这道题个人认为隐含着状态转换,所以想到的还是BFS,将其中一位数加一或减一或交换临近两位,进入下一状态,使用一个大小为10000的bool数组判重,由于BFS的特性,得到的一定是最小步数: 普通BFS ...

  3. go & RabbitMQ

    参考 RabbitMQ tutorial - 官方示例 Go code for RabbitMQ tutorials - 官方示例源码 go语言开发RabbitMQ-牛刀小小试试

  4. go & Windows Service

    相关库 https://godoc.org/golang.org/x/sys/windows/svc https://github.com/kardianos/service https://gith ...

  5. linux基本命令vi和vim使用详细介绍

    vi使用方法详细介绍 vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版 ...

  6. Elastic Search安装-windows

    转载自:https://blog.csdn.net/linkkb/article/details/82805145 其中稍作修改 ElasticSearch介绍 ES是一个基于Lucene的分布式全文 ...

  7. SSM框架的常用注解整理

    一.mybatis 1 配置一对多查询和多对多查询的注解方式映射关系: @Results:声明映射关系的配置  Value属性接收 @Result的数组 @Result:配置映射关系   id属性(b ...

  8. modesim 仿真问题

    > unisim (ERROR: Library path "d:/Xilinx/14.3/ISE_DS/ISE//vhdl/mti_se/10.1a/nt64/unisim/unis ...

  9. Linux用户的基本操作1 用户相关信息 及useradd /usermod 部分

    目录 linux 用户管理 - 用户的基本操作 用户管理 用户的相关命令 linux 用户管理 - 用户的基本操作 用户管理 1.什么是用户? 用户指的是能够正常登录Linux或windows系统 2 ...

  10. 牛客假日团队赛2 C 修围栏 ( 哈夫曼树,贪心)

    链接:https://ac.nowcoder.com/acm/contest/924/C 来源:牛客网 修围栏 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6 ...