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 ...
随机推荐
- C++基于ATL工程编写ActiveX控件步骤
参考网址: https://blog.csdn.net/whui19890911/article/details/8896554 开发环境:VS2010 开发工程:C++ATL项目 开发目的:创建Ac ...
- 【springcloud】常见面试题总结
1.springcloud与dubbo的区别? https://jingyan.baidu.com/article/b0b63dbf3784294a483070fa.html 1.1 springcl ...
- 通过location响应头实现重定向
package day08; import java.io.IOException; import javax.servlet.ServletException; import javax.servl ...
- Python - 面向对象编程 - 公共属性、保护属性、私有属性
公共属性 在 Python 的类里面,所有属性和方法默认都是公共的 class PoloBlog: # 公共属性 sum = 0 # 构造方法 def __init__(self, name): se ...
- VS2017 提示找不到某个.dll库,或某个dll库丢失,原因
可能因为那个dll的确不存在 可能因为需要在环境变量->系统环境变量->添加该dll所在目录
- Python3-sqlalchemy-orm 回滚
#-*-coding:utf-8-*- #__author__ = "logan.xu" import sqlalchemy from sqlalchemy import crea ...
- 【Office Excel】vlookup函数的反向查找实例教程,不只是正向查找,还可以反向查找,实例讲解
VLOOKUP 反向查询 众所周知,vlookup只能从左向右查找,而不能从右至左的反向查找.为此高手们设计了一个让无数新手迷惑的公式.今天优爱酷将彻底帮同学们解开这个迷团. [例]如下图所示要求根据 ...
- centos7 查看端口占用情况
2021-08-02 1. 查看端口占用情况 # 查看 8088 端口占用情况 lsof -i tcp:8088 # 若提示没有 lsof 命令, yum 安装一下 yum -y install ls ...
- (三)羽夏看C语言——进制
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
- 手动编译部署LNMP环境(CentOS7.5+Nginx-1.18.0+MySQL-5.7.30+PHP-7.4.14)
在平时运维工作中,经常需要用到LNMP应用框架.LNMP环境是指在Linux系统下,由Nginx + MySQL + PHP组成的网站服务器架构. 可参考前面的文章: 如何在CentOS 7上搭建LA ...