题面

n <= 50000,m <= 200000,k <= 12

题解

可以从K条边的两端和1结点出发各进行一次O(nlogn)的Dijk,然后就浓缩成了一个最多只有25个点的小完全图,然后就像旅行商问题一样,用状态压缩DP做。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<algorithm>
#define LL long long
using namespace std; int read() {
int f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
return x * f;
}
struct it{
int v;
LL w;
it(){}
it(int V,LL W){v = V;w = W;}
};
bool operator < (it a,it b) {
return a.w < b.w;
}
vector<it> g[50005];
vector<it> g2[50];
int n,m,i,j,s,o,k,K,e;
LL dp[30][50005],ans;
LL dp2[1<<14][30];
LL ed[30][30];
int u[17],v[17];
LL wi[17];
bool f[50005];
LL tre[200005];
LL min(LL a,LL b) {
return a < b ? a : b;
}
void maketree(int n) {
m = 1;
while(m < n + 2) m <<= 1;
for(int i = m + n + 3;i > 0;i --) {
tre[i] = 1e18;
}
}
void addtree(int x,LL y) {
int s = x + m;
tre[s] = y;
s /= 2;
while(s) {
tre[s] = min(tre[s * 2],tre[s * 2 + 1]);
s /= 2;
}
return ;
}
int searchtree(int s) {
if(s >= m) return s - m;
if(tre[s * 2] < tre[s * 2 + 1]) return searchtree(s * 2);
return searchtree(s * 2 + 1);
}
LL findtree(int l,int r) {
int s = m + l - 1;
int t = m + r + 1;
LL ans = 1e18;
while(s || t) {
if(s / 2 != t / 2) {
if(s % 2 == 0) {
ans = min(ans,tre[s + 1]);
}
if(t % 2) {
ans = min(ans,tre[t - 1]);
}
}
else break;
s >>= 1;
t >>= 1;
}
return ans;
}
void dfs(int x,int ad,LL as) {
// printf("->%d %lld\n",x % 2 ? v[x/2]:u[x/2],as);
if(as >= ans) return ;
if(ad > K * 2) {
for(int i = 0;i < g2[x].size();i ++) {
if(g2[x][i].v == 1) {
as += g2[x][i].w;
break;
}
}
ans = min(ans,as);
return ;
}
f[x] = 1;
bool flag = 0;
if(x % 2) {
if(!f[x - 1]) dfs(x - 1,ad + 1,as + wi[x / 2]);
else flag = 1;
}
else {
if(!f[x + 1]) dfs(x + 1,ad + 1,as + wi[x / 2]);
else flag = 1;
}
if(flag) {
for(int i = 0;i < g2[x].size();i ++) {
if(!f[g2[x][i].v]) {
dfs(g2[x][i].v,ad + 1,as + g2[x][i].w);
}
}
}
f[x] = 0;
return ;
}
int main() {
n = read();e = read();K = read();
v[0] = 1;
for(int i = 1;i <= e;i ++) {
s = read();o = read();k = read();
g[s].push_back(it(o,k));
g[o].push_back(it(s,k));
if(i <= K) u[i] = s,v[i] = o,wi[i] = k;
}
for(int k = 1;k <= K * 2 + 1;k ++) {
for(int i = 1;i <= n;i ++) dp[k][i] = 1e18;
int ad = (k % 2 ? v[k / 2] : u[k / 2]);
maketree(n);
memset(f,0,sizeof(f));
dp[k][ad] = 0;
addtree(ad,0);
for(int i = 1;i < n;i ++) {
int t = searchtree(1);
f[t] = 1;
addtree(t,1e18);
for(int j = 0;j < g[t].size();j ++) {
if(!f[g[t][j].v]) {
dp[k][g[t][j].v] = min(dp[k][g[t][j].v],dp[k][t] + g[t][j].w);
addtree(g[t][j].v,dp[k][g[t][j].v]);
}
}
}
}
for(int i = 1;i < K * 2 + 1;i ++) {
for(int j = i + 1;j <= K * 2 + 1;j ++) {
int a = (i % 2 ? v[i / 2] : u[i / 2]);
int b = (j % 2 ? v[j / 2] : u[j / 2]);
g2[i].push_back(it(j,dp[i][b]));
g2[j].push_back(it(i,dp[i][b]));
ed[i][j] = dp[i][b];
ed[j][i] = dp[j][a];
// printf("%d %d -- %lld(%lld)\n",a,b,dp[i][b],dp[j][a]);
}
sort(g2[i].begin(),g2[i].end());
}
ans = 1e18;
memset(f,0,sizeof(f));f[0] = 1;
for(int i = 2;i <= 1<<(K + 1);i ++)
for(int j = 1;j <= K * 2 + 1;j ++) dp2[i][j] = 1e18;
for(int j = 2;j <= K * 2 + 1;j ++) dp2[1][j] = 1e18;
// printf("%lld\n",dp2[1][1]);
for(int k = 1;k < 1<<(K + 1);k += 2) {
for(int i = k == 1 ? 1 : 2;i <= K * 2 + 1;i ++) {
if(k & (1<<(i / 2))) {
// printf("(%d,%d):%lld\n",k,a,dp2[k][a]);
for(int j = 2;j <= K * 2 + 1;j ++) {
if(int(j/2) != int(i/2) && (k & (1<<(j / 2))) == 0) {
dp2[k | (1<<(j/2))][j] = min(dp2[k | (1<<(j/2))][j],dp2[k][i] + ed[i][j + 1 - (j % 2 ? 2:0)] + wi[(j/2)]);
}
}
}
}
}
for(int i = 2;i <= K * 2 + 1;i ++) {
ans = min(ans,dp2[(1<<(K + 1)) - 1][i] + dp[i][1]);
// cout<<"*"<<((1<<(K + 1)) - 1)<<endl;
}
printf("%lld\n",ans);
return 0;
}

牛客CSP-S模拟题——十二桥问题的更多相关文章

  1. 牛客JS编程大题(二)

    11.统计数组 arr 中值等于 item 的元素出现的次数 function count(arr, item) { var num = 0; for(var i = 0;i < arr.len ...

  2. 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤

    福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑         Java全栈大联盟   ...

  3. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

  4. 牛客网Java刷题知识点之为什么HashMap和HashSet区别

    不多说,直接上干货! HashMap  和  HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的 ...

  5. 牛客网Java刷题知识点之为什么HashMap不支持线程的同步,不是线程安全的?如何实现HashMap的同步?

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  6. 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  7. 牛客网Java刷题知识点之ArrayList 、LinkedList 、Vector 的底层实现和区别

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  8. 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

    不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...

  9. 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

随机推荐

  1. SCSS 简要教程(常用指令与方法)

    Sass是成熟.稳定.强大的CSS预处理器,而SCSS是Sass3版本当中引入的新语法特性,完全兼容CSS3的同时继承了Sass强大的动态功能. 特性概览 CSS书写代码规模较大的Web应用时,容易造 ...

  2. AtCoder ABC 250 总结

    AtCoder ABC 250 总结 总体 连续若干次一样的结果:30min 切前 4 题,剩下卡在 T5 这几次卡在 T5 都是一次比一次接近, 什么 dp 前缀和打挂,精度被卡,能水过的题连水法都 ...

  3. 【Java面试】请简单说一下你对受检异常和非受检异常的理解

    Hi,我是Mic 今天给大家分享一道阿里一面的面试题. 这道题目比较基础,但是确难倒了很多人. 关于"受检异常和非受检异常的理解" 我们来看看普通人和高手的回答. 普通人: 嗯.. ...

  4. ssh隧道连接的方式连接数据库

    最好用xshell做隧道连接,其他工具没接触过过 1.先新建一个会话 2.点进刚刚建好的连接,右击属性 3.点进隧道,添加,输入映射到本地的配置 4.完成之后用数据库连接工具连接即可 参考连接: ht ...

  5. 3.shell脚本循环试题

    shell脚本循环试题 1.计算从1到100所有整数的和 #!/bin/bash a=0 for i in {1..100} #1到100 #每次循环变量i的值也为循环次数 do a=$[ $a + ...

  6. JavaGUI——Java图形用户界面

    1.Java GUI 概述 GUI(Graphical User Interface,简称 GUI,图形用户界面)是指采用图形方式显示的计算机操作用户界面,与早期计算机使用的命令行界面相比,图形界面对 ...

  7. JavaScript中用画布canvans做贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 使用 Abp.Zero 搭建第三方登录模块(一):原理篇

    ​第三方登录是基于用户在第三方平台上(如微信,QQ, 百度)已有的账号来快速完成系统的登录.注册-登录等功能. 微信的鉴权 以微信的鉴权为例: 假如你的网站有一个扫码登录的功能,会弹出一个由微信提供的 ...

  9. SAP Web Dynpro - 应用程序中的服务调用

    您可以使用服务调用来调用Web Dynpro组件中的现有功能模块. 要创建服务呼叫,您可以使用Web Dynpro工具中易于使用的向导. 您可以在ABAP工作台中启动该向导以创建服务调用. 步骤1-选 ...

  10. NHibernte 4.0.3版本中,使用Queryover().Where().OrderBy().Skip().Take()方法分页获取数据失败

    问题代码如下: var result=repository.QueryOver<modal>() .Where(p=>p.Code==Code) .OrderBy(p=>p.I ...