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 ...
随机推荐
- Ubuntu18.04忘记root密码,重置root密码
输入命令,更新root密码: sudo passwd root 然后输入新密码,再输入一次确认新密码,新密码更新完毕! 切换root账号: su 如下图所示,发现已经由zyw账号切换到root账号了!
- 【spring 注解驱动开发】Spring AOP原理
尚学堂spring 注解驱动开发学习笔记之 - AOP原理 AOP原理: 1.AOP原理-AOP功能实现 2.AOP原理-@EnableAspectJAutoProxy 3.AOP原理-Annotat ...
- C#多线程详解(一) Thread.Join()的详解
bicabo C#多线程详解(一) Thread.Join()的详解 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程 ...
- 设置一个元素的HTML内容
问题 你需要一个元素中的HTML内容 方法 可以使用Element中的HTML设置方法具体如下: Element div = doc.select("div").first(); ...
- 深入浅出Mybatis系列(二)---Mybatis入门
一.Mybatis环境搭建及简单实例 1. 新建web项目, 添加依赖包:mybatis包.数据库驱动包(我使用的是mysql).日志包(我使用的是log4j), 由于我的是maven项目, 那么添加 ...
- web整合Spring
Spring整合Web开发 时间:2017-2-2 02:17 --导入jar包1.导入Spring开发基本jar包 spring-beans-3.2.0.RELEASE.jar spr ...
- ObjectInputStream和ObjectOutputStream
package stream.object; import java.io.FileInputStream; import java.io.FileOutputStream; import java. ...
- 你知道 ES6~ES12等叫法是怎么来的吗?
你知道 ES6~ES12等叫法是怎么来的吗? 前言 作为一名前端开发,学习 JavaScript 自是天经地义的事,但是,JavaScript 的发展历史是怎样的,恐怕有相当一部分人都不太了解. 我们 ...
- 剑指 Offer 31. 栈的压入、弹出序列
剑指 Offer 31. 栈的压入.弹出序列 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如,序列 {1,2,3,4,5} 是某 ...
- Docker编排工具Docker Compose的使用
一.安装docker compose 官网推荐方式之一: sudo curl -L "https://github.com/docker/compose/releases/download/ ...