dis

【刷题】【最短路】新年好

久未见 提交于 2019-12-01 07:59:05
重庆城里有n个车站,m条双向公路连接其中的某些站。每两个车站最多用一条公路直接相连,从任何一个车站出发都可以经过一条或多条公路到达其它车站,但不同的路径需要花费的时间可能不同。在一条路径上花费的时间等于路径上所有公路需要的时间和。 佳佳的家在车站1,他有五个亲戚,分别住在车站a、b、c、d、e。过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。怎样走,才需要最少的时间? 用最短路算法,求出5个点分别的距离,和1到五个点的距离, 然后枚举完事 #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> using namespace std; int n,m; const int N=5e4+3,M=1e5+3; int tot,head[N]; struct node { int v,w,nx; }e[M<<1]; void add(int u,int v,int w) { e[++tot].v =v,e[tot].w =w,e[tot].nx =head[u],head[u]=tot; e[++tot].v =u,e[tot].w =w,e[tot].nx =head[v],head[v]=tot; } inline int read() { int x=0;char c

[AMPPZ2014] Petrol

冷暖自知 提交于 2019-12-01 07:55:18
问题描述 给定一个n个点、m条边的带权无向图,其中有s个点是加油站。 每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满。 q次询问,每次给出x,y,b,表示出发点是x,终点是y,油量上限为b,且保证x点和y点都是加油站,请回答能否从x走到y。 输入格式 第一行包含三个正整数n,s,m(2<=s<=n<=200000,1<=m<=200000),表示点数、加油站数和边数。 第二行包含s个互不相同的正整数c[1],c[2],...c[s] (1<=c[i]<=n),表示每个加油站。 接下来m行,每行三个正整数u[i],v[i],d[i] (1<=u[i],v[i]<=n,u[i]!=v[i],1<=d[i]<=10000),表示u[i]和v[i]之间有一条长度为d[i]的双向边。 接下来一行包含一个正整数q(1<=q<=200000),表示询问数。 接下来q行,每行包含三个正整数x[i],y[i],b[i] (1<=x[i],y[i]<=n,x[i]!=y[i],1<=b[i]<=2*10^9),表示一个询问。 输出格式 输出q行。第i行输出第i个询问的答案,如果可行,则输出TAK,否则输出NIE。 样例输入 6 4 5 1 5 2 6 1 3 1 2 3 2 3 4 3 4 5 5 6 4 5 4 1 2 4 2 6 9 1 5 9 6 5 8 样例输出 TAK

Luogu P5590 赛车游戏 题解

北城以北 提交于 2019-12-01 07:22:00
Luogu P5590 赛车游戏 题解 写在前面 众所周知这是一篇题解,当然这也是一篇经验的总结。 它源自于洛谷月赛,传送门: P5590 赛车游戏 笔者写下这篇题解,一是希望自己这次的错误不要再犯,二是希望能帮助大家。 题解部分 题面简析 题意大致可以概括为:给你 \(n\) 个点 \(m\) 条边的 一张图,你需要给每条边加上边权,使得 \(1-n\) 的所有路径的长度均相等。 现在感觉问题简单多了,我们可以想到暴力地添加边权(反正边权也只有 \(1~9\) ) 解题思路 很明显上面的办法是不能拿满分的。并且我拿到本题并没有想过要打暴力。 我们假设这张图存在两个顶点 \(u,v\) ,它们之间的边权为 \(val<u,v>\) 。 那么就有: \(dis[u]+val<u,v>=dis[v]\) ( \(dis\) 数组是节点 \(1\) 到其他点的路径长度最值) 至于这个最值是什么,稍后再解答。 我提出了上面那个式子,那么很明显我们要求的是 \(val<u,v>\) ,这东西一定满足 \(1≤val<u,v>≤9\) 好了,现在变形一下式子: \(1≤val<u,v>=dis[v]-dis[u]≤9\) ,看出来什么了吗? 你仔细看看: \(1≤dis[v]-dis[u]≤9\) ,差分约束? 没错,就是差分约束,约束条件: \[\left\{ \begin{aligned}

P1016 旅行家的预算——贪心

徘徊边缘 提交于 2019-11-30 19:12:57
P1016 旅行家的预算 贪心求,在当前点如果能到达距离最近的油价比他小的就直接去油价比他小的, 如果在可行范围内没有比他油价小的,就加满开到可行范围内油价最小的点; 这么做是对的,我不会证明; 还有就是,如果变量定义在外面了,在for循环里面就不要定义了,这个点卡了我一下午; 一直停止运行…… #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=520; typedef double dd; struct node { dd p,dis; }s[maxn]; dd all_dis,capa,per_dis,st_p; int n; bool cmp(node qw,node we) { return qw.dis<we.dis; } dd ans_cost,last; int main() { scanf("%lf%lf%lf%lf%d",&all_dis,&capa,&per_dis,&st_p,&n); s[0].p=st_p; for(int i=1;i<=n;i++) { scanf("%lf%lf",&s[i].dis,&s[i].p); } s[n+1].dis=all_dis; for(int i=0;i<=n;i++) { if(s[i

CJOI 2005 新年好

心不动则不痛 提交于 2019-11-29 19:21:47
简要分析: 本题要求经过一定的点的最短路 类似题目: 孤岛营救问题 易得,从 i 点出发,经过 k 点 ,到达 j 点的最短路, 一定是从 i 到 k 的最短路加上从 k 到 j 的最短路 证明 :假设:从 i 点出发,经过 k 点 ,到达 j 点的最短路,不是从 i 到 k 的最短路加上从 k 到 j 的最短路 则应存在 路径 E1(i->k)+E2(k->j)<E1min+E2min 易证得 假设不成立 枚举 从每个亲戚家出发到达其它车站所需时间 再枚举每种路径所需时间 时间复杂度(5*M log M+5^5) 可以接受 注意事项 本题是无向图,注意建图和建边 注意每次dijkstra都要重新预处理 具体代码 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int inf=2147483637,Max_N=50010,Max_M=100010; typedef pair<int,int>node; struct Edge { int dis,to,next; } E[Max_M*2];//注意是无向边 int Head[Max_N],Dis[6][Max_N]

【P4149 [IOI2011]Race】点分治

岁酱吖の 提交于 2019-11-29 19:10:19
P4149 cnt[i] 代表路径和为 i 需要的最少边数 那么我们update只要加边update就行 , 如果Clear就是删一条边的影响 然后去重复影响 注意cnt数组要开1000000 /* if you can't see the repay Why not just work step by step rubbish is relaxed to ljq */ # include <cstdio> # include <cstring> # include <iostream> # include <queue> # include <cmath> # include <map> # include <stack> # include <set> # include <sstream> # include <vector> # include <stdlib.h> # include <algorithm> //#pragma comment(linker, "/STACK:10240000,10240000") using namespace std ; # define dbg(x) cout<<#x<<" = "<< (x)<< endl # define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<

Luogu P1268 树的重量

我与影子孤独终老i 提交于 2019-11-29 15:18:37
Luogu P1268 树的重量 当 \(n=2\) 时,显然 \(ans=dis(1,2)\) . 当 \(n=3\) 时,路径总和为 \(dis(1,2)\) 加上点 \(3\) 到点 \(1\) 点 \(2\) 连线的长度。即 \(ans=dis(1,2)+\frac{dis(1,3)+dis(2,3)-dis(1,2)}{2}\) . 那么考虑 \(n\) 为任意值时,第 \(n\) 条路径可以处于点 \(1\) 到点 \(2\) ~ \((n-1)\) 的任意一条路径上产生分支,那么我们显然要找最小值,因此可得 \[ans=dis(1,2)+\sum_{i=3}^{n}(min_{j=2}^{i-1}\frac{dis(1,i)+dis(i,j)-dis(1,j)}{2})\] 但是,这道题最坑的不在于此: 因为其神奇的读入方式,我们的 \(dis(i,j)\) 是不等于 \(dis(j,i)\) 的。 这个时候,你如果直接套上面那个公式,就会错掉。 有两种处理方法: 1.在读入时初始化一下。 for(int i=1;i<=n-1;i++) { for(int j=i+1;j<=n;j++) { scanf("%d",&dis[i][j]); dis[j][i]=dis[i][j]; } } 2.因为读入的 \(dis(i,j)\) 都是 \(i<j\) 的,所以公式中把

9.3题解

余生颓废 提交于 2019-11-29 14:02:55
T1 大家考场上都想到了暴搜,并且暴搜可以过,但是为什么还是有一大半的人$WA0$了呢,因为这题细节居多,考场上我调了到快9点,才过了大样例,结果还是逃脱不了$WA0$的命运, 我太难了 其实思路上没有什么,你就枚举循环节的长度,把后面位置上有数字的对回来,看能不能合法就行了,记得疯狂调试 1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #define inf 2139062143 7 #define maxm 10010 8 #define maxp 100100 9 using namespace std; 10 struct node{ 11 int p,x; 12 }a[maxm]; 13 int t,c,m,js,tail,len,pd; 14 int b[maxp],lon[5],ma[5],st[5],mi[5],stt[5]; 15 vector <int> chan; 16 bool cmp(const node &a,const node &b) 17 { 18 return a.p<b.p; 19 } 20 int main() 21 { 22 // freopen("1.in","r",stdin);

洛谷 P3831 [SHOI2012]回家的路

浪尽此生 提交于 2019-11-29 11:37:11
洛谷 P3831 [SHOI2012]回家的路 题目: 有图。转 链接 题解: 分层图。 挺不错的,进一步理解了分层图。 分层图就是把所有图中的状态都表示出来,并且不同状态之间 互不干扰 。也就是说如果有一个问题可以用方法一解决或者方法二解决,那么分层图就可以使得不是用方法一就是用方法二,不会出现两种方法都取到的紊乱情况。 此题题意:一个网格图,横竖走一条边用时 2,只能在特定点转向,横竖转向用时 1,问两点最短用时。 因为只有走到标记的点才能转方向,也就是说,从起点到终点一定要经过标记的点才能到达(起点和终点也算标记点)。那么我们考虑的范围就只是标记的点之间的关系。 对于标记的点,是可以转方向的。 此题的决策为转向,由于只存在横向和纵向两个方向,我们对这两个方向分别建立一层。即一层只连原图横向边,一层只连纵向边。 然后第一层和第二层相同的点连一条权值为1的边,表示从横向走变成纵向走需要1的代价。 最后跑最短路即可。 #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <queue> #include <algorithm> #define N 1000005 #define M 1000005 using namespace std; struct Node {

CF1214D Treasure Island

限于喜欢 提交于 2019-11-29 07:07:29
题目链接 题目大意    一个n*m的矩阵,Vasya想要从矩阵矩阵的(1,1)(左上角)走到(n,m)(右下角),矩阵中有一些格不能走,一次只能向下或向右。现在你可以使一些格变得不能走来阻止他走到,问最少改变几个格。 (3<=n*m<=1000000) 思路    直接把起点或终点围住不就好了吗。这是我第一发WA,然后发现我好傻呀,矩阵中本来就有一些障碍。   把矩阵按行加列分层,即,    则从左上角到右下角的路径一定经过每一层的至少一个格,那么我从起点bfs一遍统计出每层能到达的格分别有多少个,我只需要把其中一层能到达的全部格都变成障碍就好,那一层需要变得少就变哪一层。于是我又WA了一发。   上述想法还有一个漏洞,就是有可能这一层的这个格是可以到达的,但是从它又到不了(n,m)(例如,下图的样例),这一层就完全可以不用把这个格变为障碍,但是统计能到达格的时候又记录了它。出现这样的情况只能因为走到有些格就在已无法到达终点了,那么这些点无异于障碍,因此加一个预处理把这样的点都变成障碍就好(注意要从终点向前找)。 代码 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n,m; 6 char s[1000006]; 7 int cnt[1000006],dis[1000006]; 8 queue<int> q;