修路

【问题描述】

村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路。对于边带权的无向图 G = (V, E),请选择一些边,使得1 <= i <= d, i号节点和 n - i + 1 号节点可以通过选中的边连通,最小化选中的所有边的权值和。

【输入格式】

第一行两个整数 n, m,表示图的点数和边数。接下来的 m行,每行三个整数 ui, vi, wi,表示有一条 ui 与 vi 之间,权值为 wi 的无向边。

【输出格式】

一行一个整数,表示答案,如果无解输出-1

【样例输入】

10 20 1
6 5 1
6 9 4
9 4 2
9 4 10
6 1 2
2 3 6
7 6 10
5 7 1
9 7 2
5 9 10
1 6 8
4 7 4
5 7 1
2 6 9
10 10 6
8 7 2
10 9 10
1 2 4
10 1 8
9 9 7

【样例输出】

8

【数据范围】

1 <= d <= 4
2d <= n <= 10^4
0 <= m <= 10^4
1 <= ui, vi <= n
1 <= wi <= 1000

题解:

考虑到d灰常小,就是斯坦纳树啦

用斯坦纳树求出以u为根,连通情况为opt的最小价值,记为f[u][opt]

由于题目只要 i 与 n - i + 1 连通,那么取出所有对称的opt,取最小值,记为ans[opt]

再暴力Dp合并

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
inline void Scan(int &x)
{
char c;
while((c = getchar()) < '' || c > '');
x = c - '';
while((c = getchar()) >= '' && c <= '') x = x * + c - '';
}
const int maxn = ;
const int inf = ;
int n, m, d, t, w;
int num, all;
bool vis[maxn];
int ans[], que[maxn];
int f[maxn][];
int tot, nex[maxn], fir[maxn], ver[maxn], pri[maxn];
inline void Ins(int x, int y, int z)
{
nex[++tot] = fir[x];
fir[x] = tot;
ver[tot] = y;
pri[tot] = z;
}
inline void Reset()
{
memset(f, / , sizeof(f));
for(int i = ; i <= d; ++i) f[i][ << num++] = ;
for(int i = n - d + ; i <= n; ++i) f[i][ << num++] = ;
all = << num;
}
inline void Spfa(int opt)
{
t = ;
while(t < w)
{
int u = que[++t];
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(f[u][opt] + pri[i] < f[v][opt])
{
f[v][opt] = f[u][opt] + pri[i];
if(!vis[v])
{
vis[v] = true;
que[++w] = v;
}
}
}
vis[u] = false;
}
}
int main()
{
Scan(n), Scan(m), Scan(d);
int x, y, z;
for(int i = ; i <= m; ++i)
{
Scan(x), Scan(y), Scan(z);
Ins(x, y, z), Ins(y, x, z);
}
Reset();
for(int opt = ; opt < all; ++opt)
{
w = ;
for(int i = ; i <= n; ++i)
{
for(int sub = opt; sub; sub = (sub - ) & opt)
f[i][opt] = min(f[i][opt], f[i][sub] + f[i][opt ^ sub]);
if(f[i][opt] != inf) que[++w] = i, vis[i] = true;
}
Spfa(opt);
ans[opt] = inf;
}
bool flag;
for(int opt = ; opt < all; ++opt)
{
flag = false;
for(int i = ; i <= d; ++i)
{
bool a = (opt & ( << i)) != ;
bool b = (opt & ( << (d << ) - i - )) != ;
if(a != b)
{
flag = true;
break;
}
}
if(flag) continue;
for(int i = ; i <= n; ++i) ans[opt] = min(ans[opt], f[i][opt]);
}
for(int opt = ; opt < all; ++opt)
for(int sub = opt; sub; sub = (sub - ) & opt)
ans[opt] = min(ans[opt], ans[sub] + ans[opt ^ sub]);
if(ans[all - ] != inf) printf("%d", ans[all - ]);
else printf("-1");
}

修路 BZOJ 4774的更多相关文章

  1. bzoj 4774: 修路

    Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 282  Solved: 132[Submit][Status][Discuss] Descriptio ...

  2. 【BZOJ4774】修路(动态规划,斯坦纳树)

    [BZOJ4774]修路(动态规划,斯坦纳树) 题面 BZOJ 题解 先讲怎么求解最小斯坦纳树. 先明白什么是斯坦纳树. 斯坦纳树可以认为是最小生成树的一般情况.最小生成树是把所有给定点都要加入到联通 ...

  3. bzoj4774 修路

    4774: 修路 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 290  Solved: 137[Submit][Status][Discuss] D ...

  4. bzoj 1196 公路修建问题

    bzoj 1196: [HNOI2006]公路修建问题 Description OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情 ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. UVA - 658 It's not a Bug, it's a Feature! (隐式图的最短路,位运算)

    隐式的图搜索,存不下边,所以只有枚举转移就行了,因为bug的存在状态可以用二进制表示,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][ ...

  2. Codeforces Round #277.5 (Div. 2)-A. SwapSort

    http://codeforces.com/problemset/problem/489/A A. SwapSort time limit per test 1 second memory limit ...

  3. vc生产垃圾清理

    @echo off echo 清除所有obj pch idb pdb ncb opt plg res sbr ilk suo文件,请稍等...... pause del /f /s /q .\*.ob ...

  4. Bootstrap 网格系统(Grid System)实例1

    Bootstrap 网格系统(Grid System)实例:堆叠水平 <!DOCTYPE html><html><head><meta http-equiv= ...

  5. shell脚本,打印九九乘法表。

    [root@localhost ~]# .sh #!/bin/bash #计算九九乘法表 ` do ` do [ $j -le $i ] && echo -n "$i*$j= ...

  6. ios之alloc和init

      复制代码 SomeObject *obj = [[SomeObject alloc] initWithCenter:centerPoint radius:radius]; 和   复制代码 Som ...

  7. 大数据学习系列之Hadoop、Spark学习线路(想入门大数据的童鞋,强烈推荐!)

    申明:本文出自:http://www.cnblogs.com/zlslch/p/5448857.html(该博客干货较多) 1 Java基础: 视频方面:          推荐<毕向东JAVA ...

  8. Windows10安装MariaDB

    截至写这篇博客为止,MariaDB官方的稳定版本为,详情访问官方地址:https://downloads.mariadb.org/ 安装之前先简单说一下MariaDB:         MariaDB ...

  9. python中enumerate()函数的用法

    描述: enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中.其英文意为:枚举,列举. 函数说明: 语法 ...

  10. linux内核数据结构

    https://blog.csdn.net/zhangskd/article/details/11225301 在看ip_acct.c相关代码时看到大量使用了 hlist_nulls_for_each ...