【BZOJ4774】修路

Description

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

Input

第一行两个整数 n, m,表示图的点数和边数。接下来的 m行,每行三个整数 ui, vi, wi,表示有一条 ui 与 vi 之间,权值为 wi 的无向边。
1 <= d <= 4
2d <= n <= 10^4
0 <= m <= 10^4
1 <= ui, vi <= n
1 <= wi <= 1000

Output

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

Sample Input

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

Sample Output

8

题解:设f[S][i]表示已经连通的关键点状态为S,当前位于点i的最小权值和。转移就是斯坦纳树。

再设g[S]表示已经连通的关键点状态为S的最小权值和。只有当S保证所有的关键点对的连通状态相同时,才可以从f[S][..]更新到g[S],最后对g数组跑枚举子集的DP即可。

P.S.我至今才会枚举子集的正确姿势~~~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <utility>
#define mp(A,B) make_pair(A,B)
using namespace std;
int n,m,d,cnt,now,tot;
int f[1<<8][10010],to[20010],next[20010],val[20010],head[10010],vis[10010],p[20],Log[1<<8],ref[1<<8],g[1<<8];
priority_queue<pair<int,int> > q;
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
inline void dij(int S,int x)
{
q.push(mp(-f[S][x],x));
int i,u;
now++;
while(!q.empty())
{
u=q.top().second,q.pop();
if(vis[u]==now) continue;
vis[u]=now;
for(i=head[u];i!=-1;i=next[i]) if(f[S][to[i]]>f[S][u]+val[i])
f[S][to[i]]=f[S][u]+val[i],q.push(mp(-f[S][to[i]],to[i]));
}
}
int main()
{
int i,a,b,c,x,y;
n=rd(),m=rd(),d=rd();
memset(head,-1,sizeof(head));
for(i=1;i<=m;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
for(i=0;i<2*d;i++) Log[1<<i]=i;
memset(f,0x3f,sizeof(f)),memset(g,0x3f,sizeof(g));
for(i=1;i<=d;i++)
{
f[1<<(i-1)][i]=0,dij(1<<(i-1),i);
f[1<<(d+i-1)][n-i+1]=0,dij(1<<(d+i-1),n-i+1);
}
for(x=1;x<(1<<(2*d));x++)
{
for(tot=0,y=x;y;y-=y&-y) p[tot++]=y&-y;
for(y=1;y<(1<<tot);y++)
{
ref[y]=ref[y^(y&-y)]|p[Log[y&-y]];
for(i=1;i<=n;i++) if(f[x][i]>f[ref[y]][i]+f[x^ref[y]][i])
f[x][i]=f[ref[y]][i]+f[x^ref[y]][i];
}
for(i=1;i<=n;i++) dij(x,i);
}
for(x=1;x<(1<<d);x++) for(i=1;i<=n;i++) g[x]=min(g[x],f[(x<<d)|x][i]);
for(x=1;x<(1<<d);x++)
{
for(tot=0,y=x;y;y-=y&-y) p[tot++]=y&-y;
for(y=1;y<(1<<tot);y++)
{
ref[y]=ref[y^(y&-y)]|p[Log[y&-y]];
g[x]=min(g[x],g[ref[y]]+g[x^ref[y]]);
}
}
if(g[(1<<d)-1]==0x3f3f3f3f) printf("-1");
else printf("%d",g[(1<<d)-1]);
return 0;
}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <utility>
#define mp(A,B) make_pair(A,B)
using namespace std;
int n,m,d,cnt,now;
int to[6010],next[6010],val[6010],head[1010],f[1<<10][1010],g[1<<10],p[15],w[15],vis[1<<10];
priority_queue<pair<int,int> > q;
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
inline void dij(int S,int x)
{
q.push(mp(-f[S][x],x));
int i,u;
now++;
while(!q.empty())
{
u=q.top().second,q.pop();
if(vis[u]==now) continue;
vis[u]=now;
for(i=head[u];i!=-1;i=next[i]) if(f[S][to[i]]>f[S][u]+val[i])
f[S][to[i]]=f[S][u]+val[i],q.push(mp(-f[S][to[i]],to[i]));
}
}
int main()
{
n=rd(),m=rd(),d=rd();
int i,j,a,b,c,x,y;
memset(head,-1,sizeof(head));
for(i=1;i<=m;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
memset(f,0x3f,sizeof(f)),memset(g,0x3f,sizeof(g));
for(i=0;i<d;i++) w[i]=rd(),p[i]=rd(),f[1<<i][p[i]]=0,dij(1<<i,p[i]);
for(x=1;x<(1<<d);x++)
{
for(y=(x-1)&x;y;y=(y-1)&x) for(i=1;i<=n;i++) f[x][i]=min(f[x][i],f[y][i]+f[x^y][i]);
for(i=1;i<=n;i++) dij(x,i);
}
for(x=1;x<(1<<d);x++) for(i=1;i<=n;i++) g[x]=min(g[x],f[x][i]);
for(x=1;x<(1<<d);x++)
{
for(i=0;i<d;i++) for(j=0;j<i;j++) if(w[i]==w[j]&&((x>>i)&1)!=((x>>j)&1)) g[x]=0x3f3f3f3f;
}
for(x=1;x<(1<<d);x++) for(y=(x-1)&x;y;y=(y-1)&x) g[x]=min(g[x],g[y]+g[x^y]);
printf("%d",g[(1<<d)-1]);
return 0;
}

【BZOJ4774/4006】修路/[JLOI2015]管道连接 斯坦纳树的更多相关文章

  1. BZOJ 4006 Luogu P3264 [JLOI2015]管道连接 (斯坦纳树、状压DP)

    题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4006 (luogu)https://www.luogu.org/probl ...

  2. BZOJ4006 JLOI2015 管道连接(斯坦纳树生成森林)

    4006: [JLOI2015]管道连接 Time Limit: 30 Sec Memory Limit: 128 MB Description 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的 ...

  3. BZOJ4006: [JLOI2015]管道连接(斯坦纳树,状压DP)

    Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1171  Solved: 639[Submit][Status][Discuss] Descripti ...

  4. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

  5. 洛谷P3264 [JLOI2015]管道连接 (斯坦纳树)

    题目链接 题目大意:有一张无向图,每条边有一定的花费,给出一些点集,让你从中选出一些边,用最小的花费将每个点集内的点相互连通,可以使用点集之外的点(如果需要的话). 算是斯坦纳树的入门题吧. 什么是斯 ...

  6. bzoj 4006 [JLOI2015]管道连接——斯坦纳树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 除了模板,就是记录 ans[ s ] 表示 s 合法的最小代价.合法即保证 s 里同一 ...

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

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

  8. bzoj 4006 管道连接 —— 斯坦纳树+状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 用斯坦纳树求出所有关键点的各种连通情况的代价,把这个作为状压(压的是集合选择情况)的初 ...

  9. 【LuoguP3264】[JLOI2015] 管道连接(斯坦那树)

    题目链接 题目描述 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的通道连接困扰.该部门有 n 个情报站,用 1 到 n 的整数编号.给出 m 对情报站 ui;vi 和费用 wi,表示情报站 u ...

随机推荐

  1. 数据结构——算法之(043)(c++各种排序算法实现)

    [申明:本文仅限于自我归纳总结和相互交流,有纰漏还望各位指出. 联系邮箱:Mr_chenping@163.com] 题目: c++ 各种排序算法实现 题目分析: 详细排序原理參考相关算法书籍 算法实现 ...

  2. JS实现点击表头表格自动排序(含数字、字符串、日期)

    这篇文章主要介绍了利用JS如何实现点击表头后表格自动排序,其中包含数字排序.字符串排序以及日期格式的排序,文中给出了完整的示例代码,并做了注释,相信大家都能看懂,感兴趣的朋友们一起来看看吧. < ...

  3. javascript时钟代码 DEMO-002

    转载自:http://www.cnblogs.com/Mygirl/archive/2012/03/30/2425832.html 正常时间显示 复制代码 <SCRIPT language=ja ...

  4. jQuery的发展史,你知道吗?

    2006年1月,jQuery的第一个版本面世,至今已经有6年多了(注:这个时间点是截止至出书时间).虽然过了这么久,但它依然以其简洁.灵活的编程风格让人一见倾心.在本篇文章中,我们将讲述jQuery的 ...

  5. ffmpeg avformat_open_input返回失败的解决办法

    用ffmpeg做的第一个程序,参考网上的代码,就出现了一些问题,其中avformat_open_input返回失败. 下面是我在网上收集到的失败信息的相关解决: /////////////////// ...

  6. c++ 参赛设置

    void report(LogWriter& lw); 代表引用原对象 void report(LogWriter lw); 代表重新拷贝构造一个对象

  7. ANSI 转 UTF-8

    ANSI和UTF-8格式都不太了解,各自好像都有好几种,下载了一个库,文件基本都是ANSI格式,linux显示乱码,原来都是在虚拟机一个个的“另存为“完成的,这次文件有点多,因此需要用命令完成. 以下 ...

  8. GC之二--GC是如何回收时的判断依据、shallow(浅) size、retained(保留) size、Deep(深)size

    回到问题“为何会内存溢出?”. 要回答这个问题又要引出另外一个话题,既什么样的对象GC才会回收? 一.对象存活方式判断方法 在上一篇文章<GC之一--GC 的算法分析.垃圾收集器.内存分配策略介 ...

  9. android获取手机屏幕分辨率

    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceSt ...

  10. C#实现大数相加

    在C#中,我们经常需要表示整数.但是,c#的基本数据类型中,最大的long也只能表示-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807之间的数 ...