题目传送门


分析

先用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. [WEB安全] CSRF攻击和防御

    一.什么是CSRF 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或 ...

  2. Lua学习笔记之迭代器、table、模块和包、元表和协程

    迭代器 迭代器是一种对象,它能够来遍历标准库模板容器中的部分或全部元素,每个迭代器对象代表容器中确定的地址,在Lua中迭代器是一种支持指针类型的结构,他可以遍历集合的每一个元素. 泛型for迭代器 泛 ...

  3. Taro兼容h5的一些小问题

    背景:先做了小程序,现在需要兼容h5 问题一:Image组件mode属性设置为aspectFill在h5上没效果 解决方法:给img加样式 object-fit: cover (例子如下) // js ...

  4. day04---系统重要文件

    系统重要的文件 /etc的重要文件 1./etc/sysconfig/network-scripts/ifcfg-eth0 [root@localhost ~]# cat /etc/sysconfig ...

  5. 亲测可行,Android Studio 查看源码出现 Source for ‘Android API xxx Platform’ not found 的解决方法

    亲测可行,Android Studio 查看源码出现 Source for 'Android API xxx Platform' not found 的解决方法 如标题中的问题,产生的原因就是 SDK ...

  6. 解析Spring中的循环依赖问题:再探三级缓存(AOP)

    前言 在之前的内容中,我们简要探讨了循环依赖,并指出仅通过引入二级缓存即可解决此问题.然而,你可能会好奇为何在Spring框架中还需要引入三级缓存singletonFactories.在前述总结中,我 ...

  7. 学会了Java 8 Lambda表达式,简单而实用

    OneAPM 摘要:此篇文章主要介绍Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等.本文系OneAPM工程师编译整理. Java是一流的面向对象语言,除了 ...

  8. 【Azure 环境】Azure CLI 获取Access Token的脚本实例

    问题描述 如何使用azure CLI命令获取到中国区的Access Token呢? 问题解答 首先,需要通过 az cloud set --name AzureChinaCloud 来设置登录中国区的 ...

  9. Java基础全程复习笔记(值得参考)

    Java基础复习笔记 第01章:Java语言概述 1. Java基础学习的章节划分 第1阶段:Java基本语法 Java语言概述.Java的变量与进制.运算符.流程控制语句(条件判断.循环结构).br ...

  10. golang开发:环境篇(三)开发利器Goland安装

    这节主要介绍下golang开发的最主要的IDE,Goland.可以有效提高开发效率.用过一段时间 IntelliJ+GO插件,其实功能上跟goland差不多.不过团队的其它开发者基本都是Goland, ...