吃货 JYY / Foodie⁡\operatorname{吃货\ JYY\ /\ Foodie}吃货 JYY / Foodie

题目链接:luogu P6085⁡\operatorname{luogu\ P6085}luogu P6085 / jzoj 3290⁡\operatorname{jzoj\ 3290}jzoj 3290

题目背景

作为 JSOI 的著名吃货, JYY 的理想之一就是吃遍全世界的美食。要走遍全世界当然需要不断的坐飞机了。而不同的航班上所提供的餐食是很不一样的:比如中国的航班会提供中餐,英国的航班有奶茶和蛋糕,澳大利亚的航班有海鲜,新加坡的航班会有冰激凌……

JYY 选出了一些他特别希望品尝餐食的航班,希望制定一个花费最少的旅游计划,能够从南京出发,乘坐所有这些航班并最后回到南京。

题目

世界上一共有 NNN 个 JYY 愿意去的城市,分别从 111 编号到 NNN 。 JYY 选出了 KKK 个他一定要乘坐的航班。除此之外,还有 MMM 个 JYY 没有特别的偏好,可以乘坐也可以不乘坐的航班。

一个航班我们用一个三元组 (x,y,z)(x,y,z)(x,y,z) 来表示,意义是这趟航班连接城市 xxx 和 yyy ,并且机票费用是 zzz 。每个航班都是往返的,所以 JYY 花费 zzz 的钱,既可以选择从 xxx 飞往 yyy ,也可以选择从 yyy 飞往 xxx 。

南京的编号是 111 ,现在 JYY 打算从南京出发,乘坐所有 KKK 个航班,并且最后回到南京,请你帮他求出最小的花费。

输入

输入数据的第一行包含两个整数 NNN 和 KKK 。

接下来 KKK 行,每行三个整数 x,y,zx,y,zx,y,z 描述必须乘坐的航班的信息,数据保证在这 KKK 个航班中,不会有两个不同的航班在同一对城市之间执飞。

第 K+2K+2K+2 行包含一个整数 MMM ,接下来 MMM 行,每行三个整数 x,y,zx,y,zx,y,z 描述可以乘坐也可以不乘坐的航班信息。

输出

输出一行一个整数,表示最少的花费。数据保证一定存在满足 JYY 要求的旅行方案。

样例输入

6 3
1 2 1000
2 3 1000
4 5 500
2
1 4 300
3 5 300

样例输出

3100

样例解释

一个可行的最佳方案为 1→2→3→5→4→11\rightarrow 2\rightarrow 3\rightarrow 5\rightarrow 4\rightarrow 11→2→3→5→4→1 。

机票所需的费用为 1000+1000+300+500+300=31001000+1000+300+500+300=31001000+1000+300+500+300=3100 。

数据范围

对于 100%100\%100% 的数据, 2≤N≤13,0≤K≤78,2≤M≤200,1≤x,y≤N,1≤z≤1042\leq N\leq 13,0\leq K\leq 78,2\leq M\leq 200,1\leq x,y\leq N,1\leq z\leq 10^42≤N≤13,0≤K≤78,2≤M≤200,1≤x,y≤N,1≤z≤104 。

思路

这道题是一道状压 dp 。

我们弄一个联通图,那要弄出欧拉回路,就是要让每个点的度数是偶数。
那我们就设 f[i]f[i]f[i] 为 iii 在三进制下每一个点度数的状态:

  1. 没有连通(度数为 000 )则状态为 000
  2. 度数是奇数,状态是 111
  3. 度数是偶数,状态是 222

那怎么求呢?
我们可以再设一个 g[i]g[i]g[i] 为 iii 在二进制下为一的每一位对应的点的度数为奇数且成为了连通块。
至于转移这个,就每次多放进去连通的两个点。

接着看怎么转移 f[i]f[i]f[i] 这个玩意。
我们就看已经连通的点,然后枚举两个点,保证一个是已经连通的,然后就连通来转移。

至于两点距离,就 Floyed 求。

求答案就枚举 fff 的每个 iii ,然后首先看有没有把所有必连的边连上,有一个没连就不可以。
接着就把度数是单数的连起来(可以用 g[i]g[i]g[i] 解决),找到所需费用最小的那个。

代码

#include<cstdio>
#include<cstring>
#include<iostream>using namespace std;struct node {int x, to, nxt;
}e[201];
int n, k, x, y, z, le[15], KK, more, m, ans = 2147483647;
int num[15], dis[15][15], hav[15], to;
int g[10001], get3[15], f[2000001];
bool yes;void add(int x, int y, int z) {e[++KK] = (node){z, y, le[x]}; le[x] = KK;e[++KK] = (node){z, x, le[y]}; le[y] = KK;
}void Floyed() {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]);
}void getg() {for (int i = 0; i < (1 << n); i++)for (int j = 0; j < n; j++)if (!(i & (1 << j)))for (int k = j + 1; k < n; k++)if (!(i & (1 << k)))g[i | (1 << j) | (1 << k)] = min(g[i | (1 << j) | (1 << k)], g[i] + dis[j][k]);
}void getf() {for (int i = 2; i < get3[n]; i++)if (f[i] != 1e9) {hav[0] = 0;for (int j = 0; j < n; j++)if (i / get3[j] % 3)hav[++hav[0]] = j;for (int j = 0; j < n; j++)if (i / get3[j] % 3 == 0) {for (int k = le[j]; k; k = e[k].nxt)if (i / get3[e[k].to] % 3) {to = i + get3[j] * 2;f[to] = min(f[to], f[i]);}for (int k = 1; k <= hav[0]; k++) {to = i + get3[j];if (i / get3[hav[k]] % 3 == 1) to += get3[hav[k]];else if (i / get3[hav[k]] % 3 == 2) to -= get3[hav[k]];f[to] = min(f[to], f[i] + dis[j][hav[k]]);}}}
}void getans() {for (int i = 0; i < get3[n]; i++) {yes = 0;for (int j = 0; j < n; j++)if (num[j] && !(i / get3[j] % 3)) {yes = 1;break;}if (!yes) {int now = i;for (int j = 0; j < n; j++)if (num[j] & 1) {if (now / get3[j] % 3 == 1) now += get3[j];else if (now / get3[j] % 3 == 2) now -= get3[j];}to = 0;for (int j = 0; j < n; j++)if (now / get3[j] % 3 == 1)to |= (1 << j);ans = min(ans, f[i] + g[to]);}}
}int main() {scanf("%d %d", &n, &k);//读入for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)if (i != j)dis[i][j] = 1e9;//初始化for (int i = 1; i <= k; i++) {scanf("%d %d %d", &x, &y, &z);//读入x--;y--;more += z;//算出一定只要少多少钱add(x, y, z);num[x]++;num[y]++;dis[x][y] = min(dis[x][y], z);dis[y][x] = min(dis[y][x], z);}scanf("%d", &m);for (int i = 1; i <= m; i++) {scanf("%d %d %d", &x, &y, &z);//读入x--;y--;dis[x][y] = min(dis[x][y], z);dis[y][x] = min(dis[y][x], z);}Floyed();//求出最短路for (int i = 0; i < (1 << n); i++) g[i] = 1e9;g[0] = 0;//初始化getg();//求出gget3[0] = 1;for (int i = 1; i <= n; i++)get3[i] = get3[i - 1] * 3;for (int i = 0; i < get3[n]; i++)f[i] = 1e9;f[2] = 0;//初始化getf();//求出fgetans();//求出额外要多多少钱printf("%d", more + ans);//输出return 0;
}

吃货 JYY / Foodie相关推荐

  1. 【jzoj 3290】【luogu P6085】Foodie / 吃货 JYY(数位DP)(欧拉回路)

    Foodie / 吃货 JYY 题目链接:jzoj 3290 / luogu P6085 题目大意 有 n 个点,有一些路径一定要走,有一些路径可以走可以不走,都有走的费用. 路径双向,然后问你从 1 ...

  2. 吃货JYY[JSOI2013][状压][欧拉回路]

    文章目录 题目 思路 代码 题目 nnn 个点 mmm 条边无向连通图,每条边有权值,指定 KKK 条边必须选,每条边可以经过多次,问从 111 出发遍历完必须边最后回到 111 的最小花费? n≤1 ...

  3. bzoj4479: [Jsoi2013]吃货jyy 欧拉回路+状态压缩Dp

    bzoj4479: [Jsoi2013]吃货jyy Description [故事背景] 作为JSOI的著名吃货,JYY的理想之一就是吃遍全世界的美食.要走遍全 世界当然需要不断的坐飞机了.而不同的航 ...

  4. BZOJ4479 [JSOI2013] 吃货jyy 解题报告(三进制状态压缩+欧拉回路)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4479 Description [故事背景] 作为JSOI的著名吃货,JYY的理想之一就是 ...

  5. 【JZOJ B组】【JSOI2013】吃货JYY

    Description 世界上一共有N个JYY愿意去的城市,分别从1编号到N.JYY选出了K个他一定要乘坐的航班.除此之外,还有M个JYY没有特别的偏好,可以乘坐也可以不乘坐的航班. 一个航班我们用一 ...

  6. bzoj 4479: [Jsoi2013]吃货jyy 欧拉回路+状压dp

    题意 世界上一共有N个JYY愿意去的城市,分别从1编号到N.JYY选出了K个他一定要乘坐的航班.除此之外,还有M个JYY没有特别的偏好,可以乘坐也可以不乘坐的航班. 一个航班我们用一个三元组(x,y, ...

  7. 【省选专题一】图论 jzoj 3290【JSOI2013】吃货JYY 状压dp+欧拉回路

    Description 世界上一共有N个JYY愿意去的城市,分别从1编号到N.JYY选出了K个他一定要乘坐的航班.除此之外,还有M个JYY没有特别的偏好,可以乘坐也可以不乘坐的航班. 一个航班我们用一 ...

  8. jzoj3290. 【JSOI2013】吃货JYY

    题目描述 Description 世界上一共有N个JYY愿意去的城市,分别从1编号到N.JYY选出了K个他一定要乘坐的航班.除此之外,还有M个JYY没有特别的偏好,可以乘坐也可以不乘坐的航班. 一个航 ...

  9. [状压DP][欧拉回路]吃货JYY

    题目描述 世界上一共有N个JYY愿意去的城市,分别从1编号到N.JYY选出了K个他一定要乘坐的航班.除此之外,还有M个JYY没有特别的偏好,可以乘坐也可以不乘坐的航班. 一个航班我们用一个三元组(x, ...

最新文章

  1. 16进制输出C语言字符常量,基础C语言:进制、常量
  2. JavaScript验证表单大全
  3. 从开源小白到 Apache Member,我的成长之路
  4. 软件架构的相关概念小汇
  5. 对付网络盗贼的三板斧
  6. ie11上vue中使用elementui的input框无法输入中文
  7. Price merge是通过org change的callback来trigger的
  8. oracle仲裁磁盘是一块磁盘吗,基于ASM冗余设计的架构,仲裁磁盘组应该如何去规划?...
  9. Ansible 管理windwos服务器(一)
  10. Android 异步任务
  11. linux aix 环境,Aix5.3安装Bash环境
  12. 通达信 c语言,通达信if语句用法,通达信公式编写
  13. linux服务器有电信和网通,Linux 双网关(电信与联通)
  14. 2018年嵌入式处理器报告:神经网络加速器的崛起
  15. java getbean不同实现_JavaBean的属性可读写,编写时set方法和get方法必须配对。
  16. 旋转屏幕时数据的保存与恢复
  17. DELL 服务器 PCI-E 6IR 通道卡 6I阵列卡8口SAS SATA (整理)
  18. c# 去掉字符串最后一个逗号
  19. angular js 循环数据(死数据) 添加数据 隔行换色 单个删除 排序
  20. bootstrap 元素

热门文章

  1. 精益生产管理十大工具
  2. 苹果官方付费升级内存_新芯片、新电脑,或许还有苹果的新未来
  3. CMS使用freemarker实现页面静态化
  4. notepad++ 快捷键的使用
  5. InstallShield 2008 And 脚本(十)
  6. 马伯骞、法老助力,realme真我5G旗舰发布
  7. 解密Linux的优势
  8. JAVA生成行程单PDF
  9. 对于obj文件转化成js
  10. flutter httpClient的封装 dio