图论 ---- dijkstra变种dp Codeforces Div2 703 E. Paired Payment
题目链接
题目大意:
无向图,但是一次一定要走两步,权值为两个边边权和的平方。求1到其他每个点的最短距离。
n∈[1,1e5],m∈[1,min(2e5,n(n−1)2)],wi∈[1,50]n\in[1,1e5],m\in[1,min(2e5,\frac{n(n-1)}{2})],w_i\in[1,50]n∈[1,1e5],m∈[1,min(2e5,2n(n−1))],wi∈[1,50]
解题思路:
图上dpdpdp
这个题的突破口在于那个权值,因为才505050非常小
一开始我最朴素的想法想把距离为2的全部连边,但是不可行
因为是每次走两条边那么就有两个限制条件:
4.1 : 到了一个点你走的边数是奇数边还是偶数边?
4.2 : 你上一条边的权值是多少?那么看到这里我们就想能不能把dijkstra里面的状态增加去跑最短路?
肯定是可以的设dp[i][j][k]dp[i][j][k]dp[i][j][k]表示你现在走到iii点,上一条边的权值是jjj,且经过的路径条数是否是k∈[0,1](表示奇数和偶数)k\in[0,1](表示奇数和偶数)k∈[0,1](表示奇数和偶数)
那么我们就可以转移了,kkk转移到k⊕1k\oplus1k⊕1的转态
如果到当前点状态是奇数奇数奇数那么直接继承前面最小的偶数偶数偶数路径,并且记录转移过来的的权值www是多少更新dpdpdp方程
如果是偶数那么就可直接平方和去更新答案
AC code
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 400010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
struct node {int nxt, to, val;
}e[maxn];
int head[maxn], cnt;
inline void add(int from, int to, int val) {e[cnt] = {head[from],to,val};head[from] = cnt ++;
}
ll dist[maxn][51][2];struct Node {int poi, w, odd, val;bool operator < (const Node & a) const {return val > a.val;}
};inline void dij() {ms(dist,0x3f);dist[1][0][0] = 0;priority_queue<Node> q;q.push({1,0,0,0});while(!q.empty()) {auto top = q.top();q.pop();for(int i = head[top.poi]; ~i; i = e[i].nxt) {int v = e[i].to, w = e[i].val;ll cost = 0;if(top.odd == 1) cost = (top.w + w) * (top.w + w);if(dist[v][w][top.odd^1] > top.val + cost) {dist[v][w][top.odd^1] = top.val + cost;q.push((Node){v,w,top.odd^1,top.val+cost});}}}
}int main() {IOS;ms(head,-1);int n, m;cin >> n >> m;for(int i = 1; i <= m; ++ i) {int u, v, val;cin >> u >> v >> val;add(u,v,val);add(v,u,val);}dij();for(int i = 1; i <= n; ++ i) {ll ans = 1e18;for(int j = 0; j <= 50; ++ j) ans = min(dist[i][j][0],ans);if(ans == 1e18) cout << "-1 ";else cout << ans << " ";}
}
图论 ---- dijkstra变种dp Codeforces Div2 703 E. Paired Payment相关推荐
- Codeforces Round #703 (Div. 2)
Codeforces Round #703 (Div. 2) 题号 题目 知识点 A Shifting Stacks 思维 B Eastern Exhibition 思维 C1 Guessing th ...
- Codeforces Round #703 (Div. 2) 题解
文章目录 A. Shifting Stacks B. Eastern Exhibition C. Guessing the Greatest D. Max Median E. Paired Payme ...
- codeforces div2 Not Assigning 题解
codeforces div2 Not Assigning 题解 原题链接 /* 题意:构造一棵素数树.素数树定义如下: 这颗树中任意一条边 or 任意两条边 权重之和为素数,每条边的权重自己分配. ...
- Codeforces Round #703 (Div. 2) A-E 题解
Shifting Stacks 给你 n 长度的数组,每个下标包含 000-nnn 个木块 其中可以将某一位置的木块向右边平移 请问是否能凑出高度严格上升的数组 一开始想简单了 直接判断木块的和是否大 ...
- Codeforces Round #703 (Div. 2)(A ~ F)超高质量题解【每日亿题2 / 19】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A. Shifting Stacks B - Eastern Exhibition C1 - G ...
- CodeForces - 1486E Paired Payment(分层图最短路)
题目链接:点击查看 题目大意:给出一个 nnn 个点 mmm 条边组成的带权无向图,规定每次只能走两条边,假设走的两条边为 a−>b−>ca->b->ca−>b−> ...
- 思维dp ---- Codeforces Round #142 (Div. 1) D. Towers
题目链接 题目大意: 你可以把第iii座塔和i+1i+1i+1座或i−1i-1i−1座合并成一个 使得到的那座塔的高度是原来两座塔的和 问最使序列变成严格不增最小合并次数 解题思路: 首先我想到的是贪 ...
- 思维dp ---- Codeforces Round #722 (Div. 1) B. Kavi on Pairing Duty [思维dp + 数学]
题目大意: 将2n2n2n个点两两相连形成n对,对于任意两个点对A和B,要求至少满足其中一条: 1.A和B的某一个完全包含于另一个中 2.A和B的长度相等.问你一共有多少种方案. 解题思路: 题解:假 ...
- 思维dp ---- Codeforces Round #711 (Div. 2) - C. Planar Reflections[dp/记忆化搜索]
题目链接 题目大意: 就是给你n个平面和一个寿命为k的衰变粒子.开始粒子从左向右飞行,粒子每经过一个平面就会产生一个副本粒子,这个副本粒子比原粒子的寿命少1,即为k-1,并且飞行方向是原粒子的反方向. ...
最新文章
- linux安装用户名,Linux_Linux下用户名修改法, 
在安装系统的时候填写 - phpStudy
- Redis运维和开发学习笔记(5) 主从复制和sentinel哨兵模式
- 【C/C++开发】C++11 并发指南二(std::thread 详解)
- freemarker文件乱码问题
- Hadoop安装详细教程 单机版
- python实现高级计算器_Python实现的复杂的计算器的代码
- VUE项目开发,使用开发者工具查看源文件
- 深度剖析Java集合之Stack
- VDI IDV VOI
- openstack常用命令
- @keyframes简单使用
- 服务——Service
- Linux 系统增加硬盘
- 软件工程-体系结构设计
- 阿里云远程桌面无法连接怎么办
- C#操作Word辅助类(word2003)(转)
- 计算机信息技术对医院医疗服务工作的影响,医院计算机信息化建设的发展与讨论...
- Linux系统目录树结构以及解释
- 复合函数求导法则及其应用
- Arduino 统计中文字符串中的中文标点符号数量