题目传送门


分析

先用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. std::weak_ptr 与 std::shared_ptr 配合使用

    std::shared_ptr<int> a = std::make_shared<int>(2); std::weak_ptr<int> b = a; a = n ...

  2. String--getline()

    #include <string> #include <sstream> #include <iostream> int main() { std::wstring ...

  3. FileBeat简单使用

    简介 首先要了解ELK架构 这种结构因为需要在各个服务器上部署 Logstash,而它比较消耗 CPU 和内存资源,所以比较适合计算资源丰富的服务器,否则容易造成服务器性能下降,甚至可能导致无法正常工 ...

  4. 使用矩池云 Docker 虚拟机安装VNC、Conda、Python及CUDA

    矩池云虚拟机支持 Docker 使用,但是由于虚拟机目前不支持启动时传递环境变量来设置VNC.Jupyterlab 连接密码,所以我们没有创建相关基础镜像(设置固定密码容易泄漏),下面给大家介绍手动安 ...

  5. 第一百零四篇:DOM事件流

    好家伙,JS基础接着学,   1.事件流 页面哪个部分拥有特定的事件? 可以把页面想象成一个同心圆, 当你戳了其中的一点,其实你同时戳中了很多个圆   当你点击一个页面中的按钮,实际上你同时点击了这个 ...

  6. Html飞机大战(十五): 上线

    好家伙,   我的飞机大战部署上线了 胖虎的飞机大战 感兴趣的可以去玩一下     (怕有人接受不了这个背景,我还贴心的准备切换背景按钮,然而这并没有什么用) 现在,我们停下脚步,重新审视这个游戏   ...

  7. Html飞机大战(十四): 分数编辑和生命值设定

    好家伙,这章让我感受到了面向对象的优势了   1.分数设置 每个种类的敌机分数都设置好了, 那么当我们击毁不同的敌机后,加上不同的分数就行了 但是我们还是要想一下,   我要在哪里放这个分数增加的方法 ...

  8. 【Azure 微服务】新创建的Service Fabric集群,如何从本地机器上连接到Service Fabric Explorer(Service Fabric状态/错误查看工具)呢?

    问题描述 当在Azure中成功创建一个Service Fabric Cluster 服务后,我们能够在它的Overview页面中发现 Service Fabric Explorer的终结点,但是打开后 ...

  9. 【Azure 应用程序见解】通过无代码方式在App Service中启用Application Insights后,如何修改在Application Insights中显示的App Service实例名呢?

    问题描述 在App Service中,可以非常容易的启动Application Insights服务.默认情况中,在Application Insights中查看信息时候,其中的对象名称默认为App ...

  10. 一文读懂图数据库 Nebula Graph 访问控制实现原理

    摘要:数据库权限管理对大家都很熟悉,然而怎么做好数据库权限管理呢?在本文中将详细介绍 Nebula Graph 的用户管理和权限管理. 本文首发 Nebula Graph 博客:https://neb ...