专题训练——[kuangbin带你飞]最短路练习
最短路练习
0. Til the Cows Come Home POJ - 2387
完美的模板题
//#include<Windows.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX_V = ;
const int MAX_E = ;
const int inf = 0x3f3f3f3f; struct ENode
{
int to;
int Next;
int w;
};
ENode Edegs[MAX_E];
int Head[MAX_V];
int Dis[MAX_V];
int tnt;
void Add_ENode(int u, int v, int w)
{
++tnt;
Edegs[tnt].to = v;
Edegs[tnt].w = w;
Edegs[tnt].Next = Head[u];
Head[u] = tnt;
++tnt;
Edegs[tnt].to = u;
Edegs[tnt].w = w;
Edegs[tnt].Next = Head[v];
Head[v] = tnt;
}
struct cmpx
{
bool operator () (int &a, int &b) const
{
return Dis[a] - Dis[b] > ;
}
}; void Dijkstra(int x)
{
priority_queue<int, vector<int>, cmpx> q;
memset(Dis, inf, sizeof(Dis));
Dis[x] = ;
q.push(x);
while (!q.empty())
{
int u = q.top();
q.pop();
for (int k = Head[u]; k != -; k= Edegs[k].Next)
{
int v = Edegs[k].to;
if (Dis[v] > Dis[u] + Edegs[k].w)
{
Dis[v] = Dis[u] + Edegs[k].w;
q.push(v);
}
}
}
} int main()
{
int t, n;
cin >> t >> n;
tnt = -;
int a, b, w;
memset(Head, -, sizeof(Head));
for (int i = ; i < t; i++)
{
cin >> a >> b >> w;
Add_ENode(a, b, w);
}
Dijkstra();
cout << Dis[n] << endl;
// system("pause");
return ;
}
1. Frogger POJ - 2253
青蛙和石头。在池塘里有2只青蛙和n块石头,石头之间有一定距离,现在一只(腿短的)青蛙想要去找另一只青蛙yuehui;给出n块石头的坐标,1号为男主青蛙所在的石头,二号为目标石头。他想尽可能的省力,每次都跳的尽量短。问它在所有可行路径中单次跳跃需要的最长距离的最小值是多少?
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
const int MAX_V= ;
const double inf= 99999999999999999.0;
typedef pair<double, double> _pair;
_pair rock[MAX_V];
double get_dis(_pair a, _pair b)
{
return sqrt(((a.first- b.first)* (a.first- b.first) )+ ((a.second- b.second)* (a.second- b.second) ) );
}
double Dis[MAX_V];
struct cmpx
{
bool operator() (int &a, int &b) const
{
return Dis[a]- Dis[b]> ;
}
};
int Front[MAX_V];
void Dijkstra(int n)
{
priority_queue<int, vector<int>, cmpx> q;
fill(Dis, Dis+ n+ , inf);
//for(int i= 1; i<= n; i ++) printf("%f\n", Dis[2]);
Dis[]= ;
Front[]= -;
q.push();
while (! q.empty() )
{
int u= q.top();
q.pop();
for (int i= ; i<= n; i ++)
{
if (i== u) continue;
double detmp= get_dis(rock[u], rock[i]);
//printf("%f---%f---%f\n", Dis[u], detmp, Dis[i]);
if (Dis[i]> Dis[u]&& Dis[i]> detmp)
{
Dis[i]= max(Dis[u], detmp);
Front[i]= u;
q.push(i);
}
//printf("%f\n", Dis[i]);
}
}
}
int main()
{
int n;
int t= ;
while (cin >> n)
{
++ t;
if (n== ) break;
for (int i= ; i<= n; i ++)
{
cin >> rock[i].first >> rock[i].second;
}
//for(int i= 2; i<= n; i ++) printf("%f\n", get_dis(rock[1], rock[i]));
Dijkstra(n);
printf("Scenario #%d\n",t);
printf("Frog Distance = %.3f\n\n", Dis[]);
double ans= -1.0;
/*for (int c= n; c!= 1; c= Front[c])
{
double cnp= get_dis(rock[c], rock[Front[c]]);
ans= max(ans, cnp);
}
printf("Frog Distance = %.3f\n\n", ans);*/
}
return ;
}
2. Heavy Transportation POJ - 1797
城市中有N个路口,M个街道,每条街道都有最大承重限制;现在我们想要驾车从1号路口到N号路口,那么运输车所允许的最大重量是多少?
(不知道为什么老是PE,懒得改了)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxv= ;
const int maxe= ;
const int inf= 0x3f3f3f3f; struct ENode
{
int to;
int w;
int Next;
};
ENode edegs[maxe];
int Head[maxv], tnt;
void init()
{
memset(Head, -, sizeof(Head));
tnt= -;
}
void Add_ENode(int a, int b, int w)
{
++ tnt;
edegs[tnt].to= b;
edegs[tnt].w= w;
edegs[tnt].Next= Head[a];
Head[a]= tnt;
++ tnt;
edegs[tnt].to= a;
edegs[tnt].w= w;
edegs[tnt].Next= Head[b];
Head[b]= tnt;
} int dis[maxv];
struct cmpx
{
bool operator() (int &a, int &b) const
{
return dis[a]- dis[b]< ;
}
};
void Dijkstra(int x)
{
priority_queue<int, vector<int>, cmpx> q;
memset(dis, , sizeof(dis));
dis[x]= inf;
q.push(x); while (! q.empty())
{
int u= q.top();
q.pop();
for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
if (dis[v]< min(dis[u], edegs[k].w))
{
dis[v]= min(dis[u], edegs[k].w);
q.push(v);
}
}
}
} int main()
{
int t, Case= ;
int n, m;
scanf("%d", &t);
while (t --)
{
++ Case;
scanf("%d %d", &n, &m);
init();
int a, b, w;
for (int i= ; i< m; i ++)
{
scanf("%d %d %d", &a, &b, &w);
Add_ENode(a, b, w);
}
Dijkstra();
printf("Scenario #%d:\n%d\n", Case, dis[n]);
}
return ;
}
3. Travel (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M) /**计蒜客复现赛:点这里*/
星系中有n 个星球,编号从1 到N。星球之间有M个隧道相连,每个隧道都有一个长度。你有一个航天器,航天器有两个属性:传输距离d 和传输次数e 。航天器只能通过短于或等于其传输距离的通道;如果传输次数耗尽,则无法再使用航天器。航天器具有等级,lv0的航天器d 和e 都等于0,你可以给你的航天器升级,每次升级都会消耗c 点花费,给你的航天器提升dx和 ex点属性。现在,告诉你n,m,m条通道的信息,还有给你的航天器升级时的c,dx,ex。
Q: 你能求出从1 到N 的最小花费吗?
A: 把原本记录到达此点最短距离的Dis[] 变成 记录到达此点所需要飞行器最低等级的Dis_Level[],这样剩下的就是普通的Dijkstra了。
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX_V= ;
const int MAX_E= ;
const int inf= 0x3f3f3f3f; struct ENode
{
int to;
int w;
int Next;
};
ENode edegs[MAX_E];
int Head[MAX_V], tnt;
void Add_ENode(int a, int b, int w)
{
edegs[++ tnt].to= b;
edegs[tnt].w= w;
edegs[tnt].Next= Head[a];
Head[a]= tnt;
edegs[++ tnt].to= a;
edegs[tnt].w= w;
edegs[tnt].Next= Head[b];
Head[b]= tnt;
} int Dis_Level[MAX_V]; //到每个点,所需要的飞船最小等级;
int deep[MAX_V]; //每个点bfs 的深度;
struct cmpx
{
bool operator() (int &a, int &b) const
{
return Dis_Level[a]- Dis_Level[b]> ;
}
};
void Dijkstra(int x, int _dis, int _cost)
{
/*x为起点, _dis是每次升级提升的传送距离, _cost是升级提升的传送次数;*/
memset(Dis_Level, inf, sizeof(Dis_Level));
memset(deep, inf, sizeof(deep));
priority_queue<int, vector<int>, cmpx> q;
Dis_Level[x]= ; //起点的飞行器等级为0;
deep[x]= ; //起点深度为0;
q.push(x);
while (! q.empty())
{
int u= q.top();
q.pop();
for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
int lev_tmp= Dis_Level[u];
while (lev_tmp* _dis< edegs[k].w|| lev_tmp* _cost< deep[u]+ )
{
/*若当前的飞行器等级不能穿越此隧道,或传送次数已用完,则升级飞行器一次;*/
lev_tmp ++;
}
if (lev_tmp< Dis_Level[v])
{
/*如果此时的飞行器等级小与之前到达点v 的飞行器等级,则更新Dis_Level[v]*/
Dis_Level[v]= lev_tmp;
deep[v]= deep[u]+ ; //深度也要 +1;
q.push(v); //加入队列;
}
}
}
}
void into()
{
memset(Head, -, sizeof(Head));
tnt= -;
} int main()
{
int n, m;
int c, d, e;
int a, b ,w;
while (~ scanf("%d %d", &n, &m))
{
scanf("%d %d %d", &c, &d, &e);
into();
for (int i= ;i< m;i ++)
{
scanf("%d %d %d", &a, &b, &w);
Add_ENode(a, b, w);
}
Dijkstra(, d, e);
if (Dis_Level[n]== inf) printf("-1\n");
else printf("%lld\n", (long long)Dis_Level[n]* c);
}
return ;
}
4.Marriage Match IV (HDU 3416)
Starvae在A市,女孩在B市。每次starvae都可以到达B市并与他喜欢的女孩一起xoxo。但是他面前有两个问题,一是starvae必须在最短的时间内到达B,所以说他必须选择最短的路径;二是每条道路只能走一次,但每座城市他可以经过多次。那么,请你告诉他:从A-->B的(完全不同的)最短路径一共有几条?
Ps:最短路径+最大流。先用Dijkstra求出A到B的最短路径并处理dis[]数组,然后依照条件(dis[v]== dis[u]+ edegs[k].w)找出所有在最短路径上的边,并建一个图2。随后就是Dinic跑最大流出结果,代码如下。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxv= ;
const int maxe= ;
const int inf= 0x3f3f3f3f; struct ENode
{
int to;
int w;
int Next;
};
ENode edegs[maxe];
int Head[maxv], tnt;
void init()
{
memset(Head, -, sizeof(Head));
tnt= -;
}
void Add_ENode(int a, int b, int w)
{
++ tnt;
edegs[tnt].to= b;
edegs[tnt].w= w;
edegs[tnt].Next= Head[a];
Head[a]= tnt;
} int dis[maxv];
struct cmpx
{
bool operator() (int &a, int &b) const
{
return dis[a]- dis[b]> ;
}
};
void Dijkstra(int x)
{
priority_queue<int, vector<int>, cmpx> q;
memset(dis, inf, sizeof(dis));
dis[x]= ;
q.push(x); while (! q.empty())
{
int u= q.top();
q.pop(); for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
if (dis[v]> dis[u]+ edegs[k].w )
{
dis[v]= dis[u]+ edegs[k].w;
q.push(v);
}
}
}
} /*建新图,跑最大流*/
ENode edegs1[maxe];
int Head1[maxv], tnt1;
void init1()
{
memset(Head1, -, sizeof(Head1));
tnt1= -;
}
void Add_ENode1(int a, int b, int w)
{
++ tnt1;
edegs1[tnt1].to= b;
edegs1[tnt1].w= w;
edegs1[tnt1].Next= Head1[a];
Head1[a]= tnt1;
++ tnt1;
edegs1[tnt1].to= a;
edegs1[tnt1].w= ;
edegs1[tnt1].Next= Head1[b];
Head1[b]= tnt1;
}
void Dijk2(int n)
{
init1();
for (int u= ; u<= n; u ++)
{
for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
if (dis[v]== dis[u]+ edegs[k].w )
{
Add_ENode1(u, v, );
}
}
}
}
int level[maxv];
bool bfs_level (int s, int t)
{
memset(level, -, sizeof(level)); //所有点的等级初始化为-1;
level[s]= ; //源点的等级为1;
int que[maxv]; //队列que:按序保存已搜索到的点;
int iq= ;
que[iq ++]= s; //先将源点s 加入队列;
for (int i= ; i< iq; i ++)
{
int u= que[i]; //取出队首元素;
if (u== t)
{
/*找到汇点t,返回*/
return true;
}
for (int k= Head1[u]; k!= -; k= edegs1[k].Next)
{
/*遍历,查找到之前未找到的、可抵达的点便加入队列*/
int v= edegs1[k].to;
if (-== level[v]&& edegs1[k].w)
{
level[v]= level[u]+ ; //深度 +1;
que[iq ++]= v;
}
}
}
return false;
}
int dfs(int now, int c_max, int t)
{
/**DFS 实现多路增广*/
/*now:起点;c_max:从源点s到节点now的最大流量;t:汇点、dfs结束的终点*/
if (now== t) return c_max; //当now== t时,c_max便是要求的最大流;
int ret= , f;
for (int k= Head1[now]; k!= -; k= edegs1[k].Next)
{
if (edegs1[k].w&& level[edegs1[k] .to]== level[now]+ )
{
/**/
f= dfs(edegs1[k].to, min(c_max- ret, edegs1[k].w), t);
edegs1[k].w-= f;
edegs1[k^].w+= f;
ret+= f;
if(ret== c_max) return ret;
}
}
return ret;
}
int dinic(int s, int t)
{
int ans= ;
while(bfs_level(s, t))
{
ans+= dfs(s, inf, t);
}
return ans;
} int main()
{
int t;
int n, m;
scanf("%d", &t);
while (t --)
{
scanf("%d %d", &n, &m);
init();
int a, b, w;
for (int i= ; i< m; i ++)
{
scanf("%d %d %d", &a, &b, &w);
Add_ENode(a, b, w);
}
int start, endd;
scanf("%d %d", &start, &endd);
Dijkstra(start);
Dijk2(n);
int ans= dinic(start, endd);
printf("%d\n", ans);
}
return ;
}
end;
专题训练——[kuangbin带你飞]最短路练习的更多相关文章
- kuangbin带你飞 最短路 题解
求一个图最短路边的办法.好像下面的那个有问题.单向边和双向边一定是有区别的.这个比较容易.参照该文的最短路网络流题目和连通图题目一题求最短路关节边 另外上述2个题目的代码好像有问题. 在UVALIVE ...
- 「kuangbin带你飞」专题十七 AC自动机
layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...
- [kuangbin带你飞]专题1-23题目清单总结
[kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...
- 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开
[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...
- 「kuangbin带你飞」专题十四 数论基础
layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...
- 「kuangbin带你飞」专题二十 斜率DP
layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...
- 「kuangbin带你飞」专题二十二 区间DP
layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...
- 「kuangbin带你飞」专题十九 矩阵
layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...
- 「kuangbin带你飞」专题十八 后缀数组
layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...
随机推荐
- Thinkpad x230i安装Ubuntu10.04发生no network devices available
这个是由于10.04版本没有集成x230i的网卡驱动导致,需要到http://sourceforge.net/projects/e1000/f ... %20stable/下载最新版本驱动,并安装,之 ...
- PCB Web版SI9000阻抗计算器
在几个月前写过一遍关于: PCB SI9000阻抗计算引擎Web方式实现方法 ,最近开始参考Polar SI9000的界面,将阻抗计算器转为网页版的方式实现. 一.Web版SI9000阻抗计算器 ...
- HDU2604:Queuing(矩阵快速幂+递推)
传送门 题意 长为len的字符串只由'f','m'构成,有2^len种情况,问在其中不包含'fmf','fff'的字符串有多少个,此处将队列换成字符串 分析 矩阵快速幂写的比较崩,手生了,多练! 用f ...
- json知识笔记
1.全称:JavaScript Object Notation 2.数据格式 3. 数据结构-object String+基本类型(或者数据结构) 数据结构-Array [基本类型] 4.一个样例a ...
- bzoj 2288: 【POJ Challenge】生日礼物【链表+堆】
参考:http://blog.csdn.net/w_yqts/article/details/76037315 把相同符号的连续数字加起来,合并后ans先贪心的加上所有正数,如果正数个数sum> ...
- bzoj3316: JC loves Mkk(单调队列+分数规划)
Description Input 第1行,包含三个整数.n,L,R.第2行n个数,代表a[1..n]. Output 仅1行,表示询问答案.如果答案是整数,就输出整数:否则,输出既约分数“P/Q”来 ...
- 【NOIP2006】作业调度方案 {语文难题}
Description: 我们现在要利用 m 台机器加工 n 个工件,每个工件都有 m 道工序,每道工序都在不同的指定的机器上完成.每个工件的每道工序都有指定的加工时间. 每个工件的每个工序称为一个 ...
- NOIp2013 货车运输 By cellur925
题目传送门 A 国有 n 座城市,编号从 1 到 n ,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下 ...
- yml文件教程
地址:http://www.ruanyifeng.com/blog/2016/07/yaml.html 原来三个横线(---)是用来区分多个文件的,像下面就是指定了两个配置. spring: appl ...
- Hdu 5379 Mahjong tree (dfs + 组合数)
题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...