Codeforces667D(spfa+dp)
题意:
给定一个带权有向图,若P(A,B)表示节点A到B的最短路长度,选择四个节点ABCD,使得P(A,B)+P(B,C)+P(C,D)最大。
节点数n在1,000以内,边数m在2,000以内。
思路:
首先先将两两点之间的最短路都算出来。
之后建立pre和next两个数组,但在这里我用结构体保存其权值和编号一直算不出正确结果,退而求其次,只保存最长路径排名前三的结点,每次遇到一个更长的边,就将另外两条边往后推一个位置,给新的最长边留出位置。
在枚举的时候,当最长边不存在的时候、最长边对应的点与b、c点冲突的时候,两个最长边对应的点彼此冲突的时候,跳过此次枚举。
最后直接输出对应的结果编号即可。
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int inf = 99999999;
const int maxn = 10000 + 5;
struct edge {
int v, w;
};
int nex[maxn][3], pre[maxn][3];
vector<vector<edge>>a;
int n, m, dis[maxn][maxn];
bool flag[maxn][maxn];
void add_edge(int u, int v, int w) {
edge tmp;
tmp.v = v;
tmp.w = w;
a[u].push_back(tmp);
}
void spfa(int s) {
queue<int>q;
q.push(s);
dis[s][s] = 0; flag[s][s] = true;
while (!q.empty()) {
int u = q.front(); q.pop(); flag[s][u] = false;
for (int i = 0; i < a[u].size(); i++) {//扫描所有邻接点
if (dis[s][a[u][i].v] > dis[s][u] + a[u][i].w) {
dis[s][a[u][i].v] = dis[s][u] + a[u][i].w;
if (!flag[s][a[u][i].v]) {
q.push(a[u][i].v);
flag[s][a[u][i].v] = true;
}
}
}
}
}
void upd() {
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 3; j++) {
nex[i][j] = -1;
pre[i][j] = -1;
}
}
int i, j;
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
if (dis[i][j] == inf) continue;
if (nex[i][0] == -1 || dis[i][nex[i][0]]<dis[i][j]){
nex[i][2] = nex[i][1];
nex[i][1] = nex[i][0];
nex[i][0] = j;
}
else if (nex[i][1] == -1 || dis[i][nex[i][1]]<dis[i][j]){
nex[i][2] = nex[i][1];
nex[i][1] = j;
}
else if (nex[i][2] == -1 || dis[i][nex[i][2]]<dis[i][j]){
nex[i][2] = j;
}
}
}
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
if (dis[j][i] == inf) continue;
if (pre[i][0] == -1 || dis[pre[i][0]][i]<dis[j][i]){
pre[i][2] = pre[i][1];
pre[i][1] = pre[i][0];
pre[i][0] = j;
}
else if (pre[i][1] == -1 || dis[pre[i][1]][i]<dis[j][i]){
pre[i][2] = pre[i][1];
pre[i][1] = j;
}
else if (pre[i][2] == -1 || dis[pre[i][2]][i]<dis[j][i]){
pre[i][2] = j;
}
}
}
}
int main() {
int u, v, w;
scanf("%d%d", &n, &m);
a.resize(maxn);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dis[i][j] = inf;
flag[i][j] = false;
}
}
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
for (int i = 1; i <= n; i++) {
spfa(i);
}
upd();
int ans = 0, str[4];
for (int b = 1; b <= n; b++) {
for (int c = 1; c <= n; c++) {
if (b == c || dis[b][c] == inf) continue;
for (int k = 0; k < 3; k++) {
for (int l = 0; l < 3; l++) {
if (pre[b][k] == -1 || nex[c][l] == -1)continue;
if (pre[b][k] == b || pre[b][k] == c)continue;
if (nex[c][l] == b || nex[c][l] == c)continue;
if (pre[b][k] == nex[c][l])continue;
int tem = dis[pre[b][k]][b] + dis[b][c] + dis[c][nex[c][l]];
if (tem > ans)
{
ans = tem;
str[0] = pre[b][k]; str[3] = nex[c][l];
str[1] = b; str[2] = c;
}
}
}
}
}
printf("%d %d %d %d\n", str[0], str[1], str[2], str[3]);
return 0;
}
Codeforces667D(spfa+dp)的更多相关文章
- 【BZOJ】1003: [ZJOI2006]物流运输trans(SPFA+DP)
http://www.lydsy.com/JudgeOnline/problem.php?id=1003 这题一开始看是不会的额,,,还是看题解了..一开始我觉得不能用最短路啥的,,看了题解发现这是d ...
- PAT 甲级 1087 All Roads Lead to Rome(SPFA+DP)
题目链接 All Roads Lead to Rome 题目大意:求符合题意(三关键字)的最短路.并且算出路程最短的路径有几条. 思路:求最短路并不难,SPFA即可,关键是求总路程最短的路径条数. 我 ...
- HDU-3499:Flight(SPFA+dp)
Recently, Shua Shua had a big quarrel with his GF. He is so upset that he decides to take a trip to ...
- BZOJ2763 [JLOI2011]飞行路线(SPFA + DP)
题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=2763 Description Alice和Bob现在要乘飞机旅行,他们选择了一家 ...
- BZOJ 1003: [ZJOI2006]物流运输(spfa+dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=1003 题意: 思路: 首先用spfa计算一下任意两天之内的最短路,dis[a][b]表示的就是在第a ...
- 51nod1326 遥远的旅途(spfa+dp)
题意: 给出一个无向图,问从1到n是否存在一条长度为L的路径. n,m<=50,1<=路径长度<=10000,L<=10^18 思路: 改变一下思路,我们发现,假设从起点1走到 ...
- 2019.01.22 bzoj3875: [Ahoi2014&Jsoi2014]骑士游戏(spfa+dp)
传送门 题意简述:nnn个怪物,对于编号为iii的怪物可以选择用aia_iai代价将其分裂成另外的bib_ibi个怪物或者用cic_ici代价直接消灭它,现在问消灭编号为1的怪物用的最小代价. ...
- ACdreamOJ 1154 Lowbit Sum (数字dp)
ACdreamOJ 1154 Lowbit Sum (数位dp) ACM 题目地址:pid=1154" target="_blank" style="color ...
- 「SDOI2016」储能表(数位dp)
「SDOI2016」储能表(数位dp) 神仙数位 \(dp\) 系列 可能我做题做得少 \(QAQ\) \(f[i][0/1][0/1][0/1]\) 表示第 \(i\) 位 \(n\) 是否到达上界 ...
随机推荐
- web渗透步骤流程
2013-11-13 23:03 (分类:网络安全) 这篇流程写的非常细,思路上很完整很全面,非常值得参考,做渗透思路要非常清晰,要不然我感觉真的容易乱,或者漏掉一些可能存在的点. 1.渗透目标 渗透 ...
- 学会这一招,小白也能使用数据可视化BI软件创建医院数据实时展示大屏
灯果数据可视化BI软件是新一代人工智能数据可视化大屏软件,内置丰富的大屏模板,可视化编辑操作,无需任何经验就可以创建属于你自己的大屏.大家可以在他们的官网下载软件. 本文以医院数据实时展示大屏为例 ...
- Java 中常见排序算法
经典的排序算法总结 冒泡排序算法 算法描述: 比较相邻的元素:如果第一个比第二个大,就交换它们两个: 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数: 针 ...
- P3078 [USACO13MAR]Poker Hands S
链接:Miku ---------------- 这道题和线段树有什么关系 --------------- 很简单的贪心,如果一堆牌比左边的大,那么肯定是要加上他的差的 反正,顺手出掉就可以了 --- ...
- Blazor client-side + webapi (.net core 3.1) 添加jwt验证流程(非host)第二步 添加Identity
添加Identity数据上下文 安装nuget包:Microsoft.AspNetCore.Identity.EntityFrameworkCore 创建ApplicationDbContext类 创 ...
- 电信IOT平台固件升级
1 离线签名 注意事项:特别重要,被坑了好久 A 将差分文件.bin格式的压缩成.zip 再进行签名 B 不能再中文目录下 否则,会出现校验失败 记住私钥 2 上传公钥 3 上传固件包 4 ...
- MSSQL sqlserver 统计"一个字符串"在"另一个字符串"中出现的次数的方法
转自 http://www.maomao365.com/?p=9858 摘要: 下文讲述sqlserver中最快获取一个字符串在另一个字符串中出现个数的方法分享 实验环境:sql server 20 ...
- Jean-Pierre Serre访问录
问:是什么使您以数学为职业的? 答:我记得大概是从七.八岁时起喜欢数学的.在中学里, 我常做一些高年级的题目.那时,我寄宿于Nimes,与比我大的孩子住在一起,他们常常欺侮我,为了平抚他们,我就经常帮 ...
- minio gateway 代理s3 存储
以前有写过使用minio gataway 代理nas 的,实际上还可以代理s3 ,hdfs....,以下是一个gatway 带来nas 以及s3 集成的模式 环境准备 docker-compose文件 ...
- MySQL基础篇(02):从五个维度出发,审视表结构设计
本文源码:GitHub·点这里 || GitEE·点这里 一.数据场景 1.表结构简介 任何工具类的东西都是为了解决某个场景下的问题,比如Redis缓存系统热点数据,ClickHouse解决海量数据的 ...