题目大意:$n$ 个点,$m$ 条边的无向图,边权只有两种,小的为 $a$,大的为 $b$。

对于每个点 $p$,询问在这张图所有的最小生成树上,$1$ 到 $p$ 的最短距离的最小值。

$2\le n\le 70,1\le m\le 200,1\le a<b\le 10^7$。


妙啊,真的太妙了。

有以下几个结论:(以下称边权为 $a$ 的叫轻边,边权为 $b$ 的叫重边)

结论 1:如果原图两个点中存在一条路径只有轻边,那么这两点在所有的最小生成树的路径上都不会有重边。根据最小生成树的性质,显然正确。

结论 2:如果把原图中所有重边删掉,会剩下一些联通块。一条路径可能在最小生成树上,当且仅当它没有离开一个联通块后再回到原来那个联通块中。根据结论 1 这也是对的。(注意,如果两个点属于一个联通块,但是这两个点有重边相连,那这个重边也是不能走的)

那么可以设计状态 $f[S][u]$,$S$ 是已经离开过的联通块集合,$u$ 是目前所在的点。

由于 $f[S][u]$ 可以转移到 $f[S][v]$ 时,$f[S][v]$ 也可以转移到 $f[S][u]$,所以要用最短路的方式更新。

时间复杂度 $O(2^nm\log(2^nm))$。其实由于边权只有两种,可以开两个队列,一个点最多被更新两次,复杂度是 $O(2^nm)$。

然而还有另一个结论:

结论 3:如果一个联通块大小 $\le 3$,那么在 $S$ 中不需要考虑这个联通块。证明,由于离开再回到一个联通块至少要两条重边(除了上面提到的直接一条重边相连,这个可以判掉),而当联通块大小 $\le 3$ 时内部可以通过不超过两条轻边互达。所以即使不记录,最优策略也不会离开再回到这个联通块。

那么只用记录大小 $\ge 4$ 的联通块即可。时间复杂度 $O(2^{n/4}m)$。

细节有点多。

#include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,m,a,b,w[][],id[],cnt,tmp,f[],q1[],q2[],h1,r1,h2,r2;
bool vis1[],vis2[];
int dfs1(int u){
vis1[u]=true;
int s=;
FOR(i,,n) if(w[u][i]==a && !vis1[i]) s+=dfs1(i);
return s;
}
void dfs2(int u,int c){
vis2[u]=true;
id[u]=c;
FOR(i,,n) if(w[u][i]==a && !vis2[i]) dfs2(i,c);
}
inline int at(int x,int y){return x*n+y-;}
int main(){
n=read();m=read();a=read();b=read();
FOR(i,,m){
int u=read(),v=read();
w[u][v]=w[v][u]=read();
}
FOR(i,,n) if(!vis1[i]) if(dfs1(i)>=) dfs2(i,++cnt);
tmp=cnt;
MEM(vis1,);
FOR(i,,n) if(!vis1[i]) if(dfs1(i)<) dfs2(i,++cnt);
MEM(f,0x7f);
f[at(,)]=;
q1[h1=r1=]=at(,);q2[h2=r2=]=at(,);
while(h1<=r1 || h2<=r2){
int u;
if(h1>r1) u=q2[h2++];
else if(h2>r2) u=q1[h1++];
else if(f[q1[h1]]<f[q2[h2]]) u=q1[h1++];
else u=q2[h2++];
int x=u/n,y=u%n+;
FOR(i,,n){
if(!w[y][i] || (id[i]<=tmp && (x&(<<(id[i]-)))) || (id[i]==id[y] && w[y][i]==b)) continue;
int v;
if(id[y]<=tmp && id[y]!=id[i]) v=at(x|(<<(id[y]-)),i);
else v=at(x,i);
if(f[v]>f[u]+w[y][i]){
f[v]=f[u]+w[y][i];
if(w[y][i]==a) q1[++r1]=v;
else q2[++r2]=v;
}
}
}
FOR(i,,n){
int ans=2e9;
FOR(j,,(<<tmp)-) ans=min(ans,f[at(j,i)]);
printf("%d ",ans);
}
}

CF1149D Abandoning Roads(图论,最短路,状态压缩,最小生成树)的更多相关文章

  1. POJ 3311 Hie with the Pie (BFS+最短路+状态压缩)

    题意:类似于TSP问题,只是每个点可以走多次,求回到起点的最短距离(起点为点0). 分析:状态压缩,先预处理各点之间的最短路,然后sum[i][buff]表示在i点,状态为buff时所耗时...... ...

  2. Light OJ 1316 A Wedding Party 最短路+状态压缩DP

    题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差点儿相同 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两 ...

  3. 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4568 题目大意: 给一个矩阵 n*m (n m<=200),方格里如果是0~9表示通过它时要花 ...

  4. Codeforces Round #556 CF1149D Abandoning Roads

    这道题并不简单,要得出几个结论之后才可以做.首先就是根据Kruskal求最小生成树的过程,短边是首选的,那么对于这道题也是,我们先做一次直选短边的最小生成树这样会形成多个联通块,这些联通块内部由短边相 ...

  5. hdu 4114 Disney's FastPass(最短路+状态压缩)

    Disney's FastPass Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  6. WOJ 1546 Maze 图论上的状态压缩DP

    http://acm.whu.edu.cn/land/problem/detail?problem_id=1546 这个题目还是聪哥教的方法过的 首先搜索是必须的,而且通过搜索来缩点,这些应该要想到, ...

  7. hdu 2489(状态压缩+最小生成树)

    Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  8. Vijos1019 补丁VS错误[最短路 状态压缩]

      描述 错误就是人们所说的Bug.用户在使用软件时总是希望其错误越少越好,最好是没有错误的.但是推出一个没有错误的软件几乎不可能,所以很多软件公司都在疯狂地发放补丁(有时这种补丁甚至是收费的).T公 ...

  9. HDU Victor and World (最短路+状态压缩)

    题目链接:传送门 题意: n个城市m条路.刚開始在点1,求把每一个城市都遍历一边最后回到1的花费的最小值. 分析: ​​+n​2​​∗2​n​​). 转自Bestcode. 以下说说我的状态转移,首先 ...

随机推荐

  1. 解决 Ubuntu16.04 + opencv4.1 源码编译错误 Makefile:160: recipe for target 'all' failed

    最近源码编译 opencv,出现下面的错误 [ %] Built target opencv_dnn Makefile:: recipe for target 'all' failed google ...

  2. ​LeetCode 26:删除排序数组中的重复项 Remove Duplicates from Sorted Array

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. Give ...

  3. Jvisualvm简单使用教程

    本博客介绍一下jvisualvm的简单使用教程,jvisualvm功能还是挺多的,不过本博客之简单介绍一下 1.拿线程快照信息 在jdk安装目录找到jvisualvm.exe,${JDK_HOME}\ ...

  4. SATA接口、PCI/PCIe、NVMe的介绍

    SATA接口.PCI/PCIe.NVMe的介绍 SATA接口 SATA是Serial ATA的缩写,即串行ATA. SATA已经完全取代旧式PATA(Parallel ATA或旧称IDE)接口的旧式硬 ...

  5. MySQL for OPS 04:存储引擎

    写在前面的话 在使用 Linux 的时候,可以经常听到有关文件系统 FS(File System)的东西,MySQL 也有属于自己类似的东西,那就是存储引擎.之前在创建数据表的时候,在 Create ...

  6. Binding ,抄自 http://www.cnblogs.com/cnblogsfans/archive/2011/02/19/1958586.html

    1. 绑定到其它元素 <Grid> <StackPanel > <TextBox x:Name="textBox1" Height="150 ...

  7. SQL server已经设置为单用户模式,Sql server还原失败数据库正在使用,无法获得对数据库的独占访问权

    如果已经设置为单用户模式,还是报这个错误的话,就按照一下SQL执行就

  8. MySql数据库中正则表达式

    命令 说明 ^ 在字符的开启处进行匹配 $ 在字符的末尾处进行匹配 . 匹配任何字符(包括回车和新行) [-.] 匹配括号内的任意单个字符 [m-n] 匹配m到n之间的任意单个字符,例如[0-9],[ ...

  9. 一款好用的SSH工具“FinalShell”

    FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. 特色功能:免费海外服务器远程桌面加速,ssh加速,双边tcp加速,内网 ...

  10. Celery 异步队列

    Celery Celery是一个功能完备即插即用的异步任务队列系统.它适用于异步处理问题,当发送邮件.或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用 ...