最短路练习

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带你飞]最短路练习的更多相关文章

  1. kuangbin带你飞 最短路 题解

    求一个图最短路边的办法.好像下面的那个有问题.单向边和双向边一定是有区别的.这个比较容易.参照该文的最短路网络流题目和连通图题目一题求最短路关节边 另外上述2个题目的代码好像有问题. 在UVALIVE ...

  2. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  3. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  4. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  5. 「kuangbin带你飞」专题十四 数论基础

    layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...

  6. 「kuangbin带你飞」专题二十 斜率DP

    layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...

  7. 「kuangbin带你飞」专题二十二 区间DP

    layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...

  8. 「kuangbin带你飞」专题十九 矩阵

    layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...

  9. 「kuangbin带你飞」专题十八 后缀数组

    layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...

随机推荐

  1. Java Socket线程的设计原理介绍

    转自:http://developer.51cto.com/art/201003/190001.htm Java Socket线程我们经常会用到的技术,但是有很多程序员还是有不少的使用问题,下面我们就 ...

  2. 使用java发送HTTP请求

    public class Test { public static void main(String[] args) { BufferedReader in = null; String result ...

  3. Linux下安装Redis及搭建主从

    Linux下安装Redis 首先在官网下载对应版本的redis包,这里本人使用的是redis-4.0.8.tar.gz.   然后在服务器中存放redis包的路径下执行tar –vxf redis-4 ...

  4. E20180218-hm-xa

    更新: 2019/02/19 原来忘记分类,把此博文归入单词类 vocabulary  n. (某一语言的) 词汇; (尤指外语教科书中附有释义的) 词汇表; grammar  n. 语法; 语法书; ...

  5. HDU1430;魔板(BFS+康托展开)

    传送门 题意 给出初始序列与终止序列,给出三种操作,问最少经过几次操作能使初始->终止,输出操作(字典序最小) 分析 字符串只有8个字符,使用康托展开. 1.BFS将所有序列从"123 ...

  6. bzoj 2618【半平面交模板】

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> usin ...

  7. 配置yum源的步骤(阿里源)

    配置yum源的步骤1.可以移除默认的yum仓库,也就是删除 /etc/yum.repos.d/底下所有的.repo文件(踢出国外的yum源) 1.配置yum源,找到阿里云的官方镜像源地址 https: ...

  8. COT2 - Count on a tree II(树上莫队)

    COT2 - Count on a tree II You are given a tree with N nodes. The tree nodes are numbered from 1 to N ...

  9. Tree POJ - 174

    点分模板题 都快改的跟题解一模一样了2333333 #include<cstdio> #include<cstring> #include<algorithm> u ...

  10. Acitivty四种启动模式

    Acitivty的四种启动模式 在清单文件中声明 Activity 时,您可以使用 <activity> 元素的 launchMode 属性指定 Activity 应该如何与任务关联. l ...