题目传送门


分析

先用Floyd求出两点间的最短距离,包含必经边的欧拉回路,

先考虑欧拉回路的性质就是度数为偶数且连通,那如果有偶数个奇点可以两两配对。

设 \(g[S]\) 表示选择 \(S\) 中的点作为奇点时最少需要的代价,则 \(g[S|2^j|2^k]=\min\{g[i]+dis[j][k]\}\)

然后考虑怎样连起来,设 \(f[S]\) 表示状态为 \(S\) 的最小代价,三进制位的0表示没有与1连通,1表示连通且度数为奇数,2表示连通且度数为偶数。

这个状态度数并不包含必经边,直接枚举必经边的端点和连通的点转移一下,最后再将必经边的度数合起来,时间复杂度 \(O(3^nn^2)\)


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
using namespace std;
const int N=16;
struct node{int y,w,next;}e[N*10]; queue<int>q; int f[1600001],g[9001];
int n,m,ans=0x3f3f3f3f,dis[N][N],et=1,as[N],a[N],_2[N],_3[N],deg[N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void add(int x,int y,int w){
e[++et]=(node){y,w,as[x]},as[x]=et;
e[++et]=(node){x,w,as[y]},as[y]=et;;
}
int min(int a,int b){return a<b?a:b;}
void doit(){
q.push(2);
while (!q.empty()){
int x=q.front(),tot=0; q.pop();
for (int i=0;i<n;++i)
if ((x/_3[i])%3) a[++tot]=i;
for (int i=0;i<n;++i)
if ((x/_3[i])%3==0){
for (int j=as[i+1];j;j=e[j].next)
if ((x/_3[e[j].y-1])%3){
int y=x+_3[i]*2;
if (f[y]<=f[x]) continue;
if (f[y]==0x3f3f3f3f) q.push(y);
f[y]=f[x];
}
for (int j=1;j<=tot;++j){
int y=x+_3[i];
if ((x/_3[a[j]])%3==1) y+=_3[a[j]];
else y-=_3[a[j]];
if (f[x]+dis[i+1][a[j]+1]>=f[y]) continue;
if (f[y]==0x3f3f3f3f) q.push(y);
f[y]=f[x]+dis[i+1][a[j]+1];
}
}
}
}
int main(){
n=iut(),_2[0]=_3[0]=1;
memset(dis,0x3f,sizeof(dis));
memset(g,0x3f,sizeof(g)),g[0]=0;
memset(f,0x3f,sizeof(f)),f[2]=0;
for (int i=1;i<=n;++i) _2[i]=_2[i-1]*2,_3[i]=_3[i-1]*3;
for (int T=iut();T;--T){
int x=iut(),y=iut(),w=iut();
dis[x][y]=dis[y][x]=w;
++deg[x],++deg[y],add(x,y,w);
}
for (int T=iut();T;--T){
int x=iut(),y=iut(),w=iut();
dis[x][y]=dis[y][x]=min(dis[x][y],w);
}
for (int k=1;k<=n;++k)
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for (int i=0;i<_2[n];++i)
for (int j=0;j<n;++j) if (!((i>>j)&1))
for (int k=j+1;k<n;++k) if (!((i>>k)&1))
g[i|_2[j]|_2[k]]=min(g[i|_2[j]|_2[k]],g[i]+dis[j+1][k+1]);
doit();
for (int S=0;S<_3[n];++S){
bool flag=0;
for (int i=0;i<n;++i)
if (as[i+1]&&(S/_3[i])%3==0){
flag=1; break;
}
if (flag) continue;
int now=S;
for (int i=0;i<n;++i) if (deg[i+1]&1)
now+=((S/_3[i])%3==1)?_3[i]:-_3[i];
int _S=0;
for (int i=0;i<n;++i)
if ((now/_3[i])%3==1)
_S|=_2[i];
ans=min(ans,f[S]+g[_S]);
}
for (int i=2;i<=et;i+=2) ans+=e[i].w;
return !printf("%d",ans);
}

#欧拉回路,状压dp,Floyd#洛谷 6085 [JSOI2013]吃货 JYY的更多相关文章

  1. 最短路+状压DP【洛谷P3489】 [POI2009]WIE-Hexer

    P3489 [POI2009]WIE-Hexer 大陆上有n个村庄,m条双向道路,p种怪物,k个铁匠,每个铁匠会居住在一个村庄里,你到了那个村庄后可以让他给你打造剑,每个铁匠打造的剑都可以对付一些特定 ...

  2. 状压DP 【洛谷P3694】 邦邦的大合唱站队

    [洛谷P3694] 邦邦的大合唱站队 题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶 ...

  3. 状压DP【洛谷P1879】 [USACO06NOV]玉米田Corn Fields

    P1879 [USACO06NOV]玉米田Corn Fields 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形 ...

  4. 状压DP【洛谷P1896】 [SCOI2005]互不侵犯

    P1896 [SCOI2005]互不侵犯 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子 ...

  5. 【状压DP】SCOI2005-洛谷P1896-互不侵犯 (状压例题)

    [状压DP]SCOI2005-洛谷P1896-互不侵犯 (状压例题) 标签(空格分隔): 状压DP 好久没写博客了,真的爽(误) 题目: 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方 ...

  6. loj #6177. 「美团 CodeM 初赛 Round B」送外卖2 状压dp floyd

    LINK:#6177.美团 送外卖2 一道比较传统的状压dp题目. 完成任务 需要知道自己在哪 已经完成的任务集合 自己已经接到的任务集合. 考虑这个dp记录什么 由于存在时间的限制 考虑记录最短时间 ...

  7. 【wikioi】2800 送外卖(状压dp+floyd)

    http://www.wikioi.com/problem/2800/ 本题状压莫名其妙的tle了,(按照hzwer大神打的喂,他1000多ms,我就2000ms了?) (14.8.7更,将getnu ...

  8. POJ 3311 Hie with the Pie(状压DP + Floyd)

    题目链接:http://poj.org/problem?id=3311 Description The Pizazz Pizzeria prides itself in delivering pizz ...

  9. hdu_5418_Victor and World(状压DP+Floyd)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 题意:给你n个点,和一些边,找一条路径经过全部的点,并回到起点,问最小的花费是多少, 题解:m& ...

  10. poj3311 状压dp+floyd

    先floyd预处理一遍dis,枚举所有状态,dp[ i ] [ j ]表示 以  j  为终点的状态 i 使用最小的时间 #include<map> #include<set> ...

随机推荐

  1. 多线程系列(七) -ThreadLocal 用法及内存泄露分析

    一.简介 在 Java web 项目中,想必很多的同学对ThreadLocal这个类并不陌生,它最常用的应用场景就是用来做对象的跨层传递,避免多次传递,打破层次之间的约束. 比如下面这个HttpSer ...

  2. MacBook M1 VulnHub靶机搭建(arm Mac搭建x86 ova镜像)

    个人博客: xzajyjs.cn 自从换了M1系的arm Mac后,原本的Vulnhub上的几乎所有靶场按照之前的方法都无法正常搭建了(VirtualBox),在外网论坛上找了一遍,有一个相对麻烦一些 ...

  3. 【算法day4】堆结构、堆排序、比较器以及桶排

    堆与堆结构(优先级队列结构) 知识点: 堆结构就是用数组实现的完全二叉树结构 完全二叉树中如果每棵子树的最大值都在顶部就是大根堆 完全二叉树中如果每棵子树的最小值都在顶部就是小根堆 堆结构的heapl ...

  4. Redis动态配制,限内存,免重启

    p.p1 { margin: 0; font: 14px Menlo; color: rgba(0, 255, 255, 1); background-color: rgba(0, 0, 0, 0.8 ...

  5. 【应用服务 App Service】 App Service Rewrite 实例 -- 限制站点的访问

    问题描述 在Azure App Service中,当需要限制某些特殊的情况对其进行访问时候,可以通过IP限制,逻辑代码判断,或者Rewrite规则.通过IP限制则需要知道客户端访问的IP,而通过逻辑代 ...

  6. 第12章_MySQL数据类型

    目录: https://www.cnblogs.com/xjwhaha/p/15844178.html 1. MySQL中的数据类型 类型 类型举例 整数类型 TINYINT.SMALLINT.MED ...

  7. Java面试挂在线程创建后续,不要再被八股文误导了!创建线程的方式只有1种

    写在开头 在上篇博文中我们提到小伙伴去面试,面试官让说出8种线程创建的方式,而他只说出了4种,导致面试挂掉,在博文中也给出了10种线程创建的方式,但在文章的结尾我们提出:真正创建线程的方式只有1种,剩 ...

  8. 摆脱鼠标系列 - vscode 软件 最大化快捷键 - win + ↑

    摆脱鼠标系列 - vscode 软件 最大化快捷键 - win + ↑ vscode默认打开不是最大化,所以按 win + 上箭头 使其最大化 不想按 F11 那个不太方便,左上角就没有项目名称了 优 ...

  9. iview select 下拉 多选 数组 外面包一层 数组改逗分,外层不能用v-model 要用 :value @input,input里面要把对象解构下,才能过验证 - vue

    iview select 下拉 多选 数组 外面包一层 数组改逗分,外层不能用v-model 要用 :value @input,input里面要把对象解构下,才能过验证 - vue

  10. rancher添加用户报错x509: certificate has expired Internal error occurred: failed calling webhook "rancherauth.cattle.io":

    错误信息: Internal error occurred: failed calling webhook "rancherauth.cattle.io": Post https: ...