HDOJ 6664 Andy and Maze
HDOJ题目页面传送门
给定一个无向带权图\(G=(V,E),|V|=n,|E|=m\),求边权之和最大的有\(s\)个节点的链的边权之和,即求\(\max\limits_{\forall i\in[1,s],\forall j\in(i,s],a_i\ne a_j,\forall i\in[1,s),(a_i,a_{i+1},l_i)\in E}\left\{\sum\limits_{i=1}^{s-1}l_i\right\}\)。如果没有符合要求的链,输出\(\texttt{impossible}\)。
\(n\in\left[2,10^4\right],m\in\left[1,10^4\right],s\in[2,6]\)。本题多测,最多有\(35\)组数据,\(\max(n,m)>100\)的最多有\(5\)组。时限\(15\mathrm s\)。
先说\(1\)种不是正解的玄学方法
暴搜。。。时间复杂度\(\mathrm O(\mathrm C_n^s)\),但很显然非常跑不满,因为这是个稀疏图。而且还可以最优性剪枝优化,假设所有边中最大的边权为\(longest\),当前的最大答案为\(ans\),当前还剩\(rst\)个节点(条边)要搜,目前的边权之和为\(now\),那么如果\(now+rst\times longest\le ans\),便可立即停止搜索。这样就可以水过去了。。。
这不是主要内容,时间复杂度到底是多少就不研究了,代码也不贴了。
正解
考虑对一个比原问题弱一点的问题求解:给每个节点\(i\)染一个\([0,s)\)的颜色\(col_i\),求边权之和最大的有\(s\)个节点且这\(s\)个节点的颜色是\(0\sim s-1\)的一个排列的链的边权之和。这个问题很好求,状压DP就可以了。设\(dp_{i,j}\)表示边权之和最大的以\(i\)为\(1\)个端点,上面节点颜色互不相同且bitmask为\(j\)的链的边权之和,边界为\(dp_{i,\{j\}}=\begin{cases}0&i=j\\-\infty&i\ne j\end{cases}\),状态转移方程为\(dp_{i,j}=\begin{cases}\max\limits_{(i,k,l)\in E}\left\{dp_{k,j-\{col_i\}}+l\right\}&col_i\in j\\-\infty&col_i\notin j\end{cases}\),最终答案为\(\max\limits_{i=1}^{n}\{dp_{i,[1,n]\cap\mathbb Z}\}\)。DP顺序要注意,要按照\(j\)的递增顺序DP,不能按照\(i\)的顺序(我就在上面WA过)。(简单DP
那么既然这个弱问题这么好求,那我们就强制给每个节点染色。假设我们给每个节点随机染色,那我们来分析一下弱问题的答案就是原问题的正确答案的概率:如果原问题所求得的最长链,在弱问题中,上面所有节点的颜色正好组成\(0\sim s-1\)的一个排列,那么弱问题的答案就是原问题的答案,而在所有\(s^s\)种最长链的颜色序列中,有\(s!\)种是\(0\sim s-1\)的排列,所以概率为\(\dfrac{s!}{s^s}\)。当\(s=6\)时,概率最小为\(\dfrac{6!}{6^6}\approx1.5\%\)。那么我们只需要在\(35\)组数据中每组随机染色、求解足够多次,就有足够大的的概率在每组中都至少有一次弱问题的答案是原问题的答案,这样把每次弱问题的答案\(\max\)起来即可。我们希望这个概率至少为\(99\%\),设随机\(x\)次,那么可以列出不等式\(\left(1-\left(1-\dfrac{6!}{6^6}\right)^x\right)^{35}\ge99\%\)。不难解出\(x\ge524.397\cdots\)。但由于HDOJ比较卡常,随机\(525\)次会TLE,于是我们只能用正确率换时间,只随机\(300\)次,这样才能勉强卡进\(15\mathrm s\)的时限。此时正确率为\(\left(1-\left(1-\dfrac{6!}{6^6}\right)^{300}\right)^{35}\approx71.8\%\),侥幸过。
btw,随机的时候不能写rand()*rand()%s。第一,在某些系统下两个rand()乘起来会爆int;第二,把两个随机数乘起来,期望因数个数会增加很多,\(\bmod s\)的结果等于\(0\)的概率也就会增加很多,就不均匀了。可以这样写:abs(rand()*rand()*rand()+rand())%s。
UPD 2020.4.12:你看看,ycx,你看看,上面那段删除线写的是smjbwy,狗屁不通。。看来我还是太年轻了。昨天经hsc神仙的提醒才知道,abs(rand()*rand()*rand()+rand())这样的写法会生成出来分布极度不均匀的随机数,虽然在本题里没事,但显然不应该这么写。不如直接用mt19937,先定义一个随机数生成器mt19937 rng;,那么\([l,r]\)之间的随机数就是uniform_int_distribution<>(l,r)(rng)。
下面贴正解的代码:(UPDed 2020.4.12)
#include<bits/stdc++.h>
using namespace std;
#define int long long//爆int
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define uid uniform_int_distribution
const int inf=0x3f3f3f3f3f3f3f3f;
mt19937 rng(20060617/*信仰优化*/);
int ppc(int x){return __builtin_popcount(x);}
const int N=10000,S=6;
int n/*节点数*/,m/*边数*/,s/*要求的链的节点数*/;
vector<pair<int,int> > nei[N+1];//邻接表
int col[N+1];//颜色
int ans;//原问题答案
int dp[N+1][1<<S];
void random(){
for(int i=1;i<=n;i++)col[i]=uid<>(0,s-1)(rng);//随机染色
for(int i=1;i<=n;i++)for(int j=1;j<1<<s;j++)dp[i][j]=j==1<<col[i]?0:-inf;//处理边界,顺便初始化
for(int j=1;j<1<<s;j++)for(int i=1;i<=n;i++)if(j&1<<col[i]&&ppc(j)>1/*大小为1的bitmask是边界*/)//枚举状态
for(int k=0;k<nei[i].size();k++){//转移
int x=nei[i][k].X,len=nei[i][k].Y;
dp[i][j]=max(dp[i][j],dp[x][j^1<<col[i]]+len);
}
for(int i=1;i<=n;i++)ans=max(ans,dp[i][(1<<s)-1]);//把每次弱问题的答案max起来就有大概率是原问题的答案
}
void mian(){
cin>>n>>m>>s;
for(int i=1;i<=n;i++)nei[i].clear();//数据不清空,爆零两行泪
while(m--){
int x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
nei[x].pb(mp(y,z));nei[y].pb(mp(x,z));
}
ans=-inf;//初始化
int randomnum=300;//随机次数
while(randomnum--)random();//随机
if(ans>=0)cout<<ans<<"\n";
else puts("impossible");
}
signed main(){
int testnum;//数据组数
cin>>testnum;
while(testnum--)mian();
return 0;
}
HDOJ 6664 Andy and Maze的更多相关文章
- 【HDOJ6664】Andy and Maze(color coding)
题意:给定一张n点m边的无向带权图,问从任意结点出发,不能走已经经过的点,共经过k个点的最长路径的值 n,m<=1e4,k<=6 思路:color coding算法 考虑每次给每个点随机编 ...
- 2019DX#8
Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Acesrc and Cube Hypernet 7.32%(3/41) 1002 A ...
- hdoj 5094 Maze 【BFS + 状态压缩】 【好多坑】
Maze Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Others) Total Sub ...
- HDU 4067 hdoj 4067 Random Maze 最小费用流
给出n个点,m条边,入口s和出口t,对于每条边有两个值a,b,如果保留这条边需要花费:否则,移除这条边需要花费b. 题目要求用最小费用构造一个有向图满足以下条件: 1.只有一个入口和出口 2.所有路都 ...
- 【HDOJ】1484 Basic wall maze
BFS. /* 1484 */ #include <iostream> #include <queue> #include <string> #include &l ...
- BFS+贪心 HDOJ 5335 Walk Out
题目传送门 /* 题意:求从(1, 1)走到(n, m)的二进制路径值最小 BFS+贪心:按照标程的作法,首先BFS搜索所有相邻0的位置,直到1出现.接下去从最靠近终点的1开始, 每一次走一步,不走回 ...
- 最大流增广路(KM算法) HDOJ 1533 Going Home
题目传送门 /* 最小费用流:KM算法是求最大流,只要w = -w就可以了,很经典的方法 */ #include <cstdio> #include <cmath> #incl ...
- BFS HDOJ 1728 逃离迷宫
题目传送门 /* BFS:三维BFS,加上方向.用dp[x][y][d]记录当前需要的最少转向数 */ #include <cstdio> #include <algorithm&g ...
- 离散化+BFS HDOJ 4444 Walk
题目传送门 /* 题意:问一个点到另一个点的最少转向次数. 坐标离散化+BFS:因为数据很大,先对坐标离散化后,三维(有方向的)BFS 关键理解坐标离散化,BFS部分可参考HDOJ_1728 */ # ...
随机推荐
- vue-router路由高亮效果
审查代码,查看激活类名 (1)设置激活类名样式 (2)也可以在路由文件里配置激活类名的别名 (3)配置别名后再次审查,如下所示 此时可以直接配置active类名样式即可 此时便可以实现路由高亮效果 .
- python移动目录下所有子目录文件到新的总目录
python移动目录下所有子目录文件到新的总目录 import os import shutil def file(p): p=p z=os.listdir(p) for i ...
- git常用命令(测试必备)
什么是git 百度百科:Git(读音为/gɪt/)是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. git相对svn,有很多优势,这里就不再赘述,大家网上搜索吧. g ...
- vector、ArryList、LinkedList的区别与联系
vector.ArryList.LinkedList的区别与联系 vectory类:底层 采用数组结构算法,使用了线程锁(synchronized),线程安全,但是性能相对ArryList比较低. A ...
- HTML元素脱离文档流的三种方法
一.什么是文档流? 将窗体自上而下分成一行一行,并在每行中按从左至右依次排放元素,称为文档流,也称为普通流. 这个应该不难理解,HTML中全部元素都是盒模型,盒模型占用一定的空间,依次排放在HTML中 ...
- USACO Superprime Rib
洛谷 P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib 洛谷传送门 JDOJ 1673: Superprime Rib JDOJ传送门 题目描述 农民约翰的母牛总是产生最好 ...
- 【oracle】decode函数
DECODE(参数,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值) 值1:当参数=值1 翻译值1:想要得到的值 值2:当参数=值2 翻译值2:想要得到的值
- OpenCV 学习笔记(13)图像转换成视频
关键 1参数里的分辨率是图像本身的分辨率,而不是指定生成的视频分辨率.如果要修改分辨率,要么后期软件处理,要么读图的时候resize 2要正常退出,不要强制退出. 3生成的只能是avi格式. #inc ...
- docker的简单操作和端口映射
一:简介 Docker镜像 在Docker中容器是基于镜像启动的 镜像是启动容器的核心 镜像采用分层设计,最顶层为读写层 使用快照COW技术,确保底层不丢失 通过ifconfig(ip a)来查看d ...
- 微信小程序 scroll-view 横向滚动条 隐藏无效
看了许多网上教程说是添加如下样式可以解决,我加入到组件wxss中无效,加入全局wxss生效. 添加css代码如下: ::-webkit-scrollbar { ; ; color: transpare ...