P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】
正题
题目链接:https://www.luogu.com.cn/problem/P6085
题目大意
\(n\)个点的一张无向图,有\(k\)条必走边,\(m\)条其他边,求从\(1\)出发经过必走边后回到起点的最短路径。
\(2\leq n\leq 13,0\leq k\leq 78,2\leq m\leq 200\)
解题思路
可以理解为在只包含必走边的图上加若干条其他边使得这张图存在欧拉回路。
欧拉回路要求所有点联通且度数为偶数,考虑状态压缩\(dp\),设三进制的状态。
\(f_s\),\(0\)表示没有联通,\(1\)表示度数为奇数,\(2\)表示度数为偶数。
然后先考虑加点进来的方式,也就是加进来的点我们只考虑不是必须的边的部分。而且使用这些点类似于一棵树的连接联通的点。(并不是连接成真正的树,而是如果使用了不必须的边的话只和一个点联通)
然后处理完后再考虑调整图的奇偶性,设\(g_S\)表示集合\(S\)中的点为奇数时调整为偶数的最小代价。
然后用\(f\)和\(g\)计算答案就好了。
时间复杂度\(O(3^nn^2)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=14;
struct node{
int to,next;
}a[N*N];
int n,k,m,tot,ans,sta,st,ls[N],p[N],deg[N];
int dis[N][N],g[1<<N],f[1594323];
queue<int> q;
void addl(int x,int y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
int main()
{
memset(dis,0x3f,sizeof(dis));
memset(g,0x3f,sizeof(g));
memset(f,0x3f,sizeof(f));
scanf("%d%d",&n,&k);p[0]=1;dis[0][0]=0;
for(int i=1;i<=n;i++)p[i]=p[i-1]*3,dis[i][i]=0;
for(int i=1;i<=k;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);x--;y--;
addl(x,y);addl(y,x);dis[x][y]=dis[y][x]=min(dis[x][y],w);
deg[x]++;deg[y]++;sta^=(1<<x)^(1<<y);ans+=w;
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);x--;y--;
dis[x][y]=dis[y][x]=min(dis[x][y],w);
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
int MS=(1<<n);g[0]=0;
for(int s=0;s<MS;s++)
for(int i=0;i<n;i++){
if((s>>i)&1)continue;
for(int j=i+1;j<n;j++)
if(!((s>>j)&1)){
int z=s^(1<<i)^(1<<j);
g[s^z]=min(g[s^z],g[s]+dis[i][j]);
}
}
q.push(2);f[2]=0;
while(!q.empty()){
int s=q.front();q.pop();
for(int x=0;x<n;x++){
if(s/p[x]%3)continue;
int t=s+p[x]*2;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(!(s/p[y]%3))continue;
if(f[t]>=g[MS])q.push(t);
f[t]=min(f[t],f[s]);
}
for(int y=0;y<n;y++){
if(!(s/p[y]%3))continue;
t=s+p[x];
if((t/p[y]%3)==2)t-=p[y];
else t+=p[y];
if(f[t]>=g[MS])q.push(t);
f[t]=min(f[t],f[s]+dis[x][y]);
}
}
}
int mins=g[MS];
for(int s=0;s<p[n];s++){
bool flag=0;int st=0;
for(int i=0;i<n;i++){
if((s/p[i]%3)==0&°[i]){flag=1;break;}
if(s/p[i]%3)st|=(1<<i)*(2-s/p[i]%3);
}
if(flag)continue;st^=sta;
mins=min(mins,f[s]+g[st]);
}
printf("%d\n",ans+mins);
return 0;
}
P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】的更多相关文章
- BZOJ 4479: [Jsoi2013]吃货jyy
一句话题意:求必须包含某K条边的回路(回到1),使得总权值最小 转化为权值最小的联通的偶点 令F[i]表示联通状态为i的最小权值,(3^n状压)表示不在联通块内/奇点/偶点,连边时先不考虑必选的边的度 ...
- BZOJ4479 [JSOI2013] 吃货jyy 解题报告(三进制状态压缩+欧拉回路)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4479 Description [故事背景]作为JSOI的著名吃货,JYY的理想之一就是吃 ...
- BZOJ4479 : [Jsoi2013]吃货jyy
若$k\leq 15$,那么可以设$d[i][S]$表示经过了$S$集合的边,现在位于$i$点的最短路. 可以用Dijkstra算法在$O(n^22^k)$时间内求出. 否则若$k>15$,那么 ...
- P1433 吃奶酪(洛谷)状压dp解法
嗯?这题竟然是个绿题. 这个题真的不(很)难,我们只是不会计算2点之间的距离,他还给出了公式,这个就有点…… 我们直接套公式去求出需要的值,然后普通的状压dp就可以了. 是的状压dp. 这个题的数据加 ...
- [状压DP]吃奶酪
吃 奶 酪 吃奶酪 吃奶酪 题目描述 房间里放着 n n n 块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 ( 0 , 0 ) (0,0) (0,0)点处. 输入 第一行有一个整 ...
- 洛谷 P1433 吃奶酪 状压DP
题目描述 分析 比较简单的状压DP 我们设\(f[i][j]\)为当前的状态为\(i\)且当前所在的位置为\(j\)时走过的最小距离 因为老鼠的坐标为\((0,0)\),所以我们要预处理出\(f[1& ...
- 【BZOJ-1097】旅游景点atr SPFA + 状压DP
1097: [POI2007]旅游景点atr Time Limit: 30 Sec Memory Limit: 357 MBSubmit: 1531 Solved: 352[Submit][Sta ...
- 【62测试】【状压dp】【dfs序】【线段树】
第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ...
- Codeforces Round #321 (Div. 2) D. Kefa and Dishes 状压dp
题目链接: 题目 D. Kefa and Dishes time limit per test:2 seconds memory limit per test:256 megabytes 问题描述 W ...
随机推荐
- easyexcel-导入
package com.meeno.framework.util.easyexcel.entity; import cn.afterturn.easypoi.excel.annotation.Exce ...
- Servlet、ServletContext与ServletConfig的详解及区别
Servlet.ServletContext与ServletConfig的详解及区别 一.Servlet详解 Servlet是一个interface,全局限定名:javax.servlet.Servl ...
- SpringBoot博客开发之异常处理
异常处理: 背景: 最近在搭建属于自己的个人博客(码农小白的执念),自己搭建后端的时候首先考虑的是异常处理.个人也是一边学习一边做,难免有疏漏的地方,希望朋友们在不对的地方提醒下. 技术栈: spri ...
- Linux从头学10:三级跳过程详解-从 bootloader 到 操作系统,再到应用程序
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- 剑指 Offer 36. 二叉搜索树与双向链表
剑指 Offer 36. 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 为了让您更好地理解问题,以下面的 ...
- idea无法使用中文输入法输入
问题--idea无法使用中文输入 原因:idea本身版本过高,所以需要你强制减低它的jdk版本 解决:使用配置idea环境变量解决 ps:目前适用于任何版本的jdk和idea 步骤: 1.新建一个ID ...
- IO和零拷贝
I/O介绍 I/O主要为:网络IO(本质是socket文件读取).磁盘IO 每次IO,都要经由两个阶段: 第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长 第二步:将数据 ...
- scrapy抓取的页面中文会变成unicode字符串
不了解编码的,需要先补下:http://www.cnblogs.com/jiangtu/p/6245264.html 在学习&使用scrapy抓取网上信息时,发现scrapy 会将含有中文的f ...
- Linux处理二进制文件工具
处理目标文件的工具 在Linux系统中有大量可用的工具可以帮助我们理解和处理目标文件.特别地,GNU binutils包尤其有帮助,而且可以运行在每一个Linux平台上 序号 命令 说明 1 AR 创 ...
- 学习反射例子,调用DLL窗体及方法
创建类库,并添加新窗体,加入以下方法 public static string setText(string str) { return str; } 编译后把生成的DLL文件放入新项目的bin目录, ...