图论——最短路

Tyvj 1221 微子危机——战略

背景

№.3
Summer联盟战前兵力战略转移。

描述

Summer的兵力分布在各个星球上,现在需要把他们全部转移到某个星球上。
Summer一共拥有N个星球(1~N),你要把这N个星球上的兵力转到第M个星球上。本来每个星球之间都有星际轨道连接,但Guiolk监视了某些轨道,我们一但走上这些轨道,有可能受到他的攻击。为了安全,Summer不会走被监视的轨道。于是,只有L个星际轨道是被批准通过的。Summer的国防部想统计一下所需的最短路程(即每个星球到第M星球的最短路程总和,单位:M  PS:‘M‘不是米)。

输入格式

第一行有三个正整数,N,M,L(分别如题目描述)接下来L行,为被批准通行的轨道。每行有三个整数:a,b,c,表示第a个星球和第b个星球之间的轨道长cM(有重复)。

输出格式

如果所有星球上的兵力能全部集中到第M个星球,则输出: 最短路程和+“ M(s) are needed.”如果某个星球的兵力不能到达第M个星球,则输出“Sth wrong.”。

测试样例1

输入

【样例输入1】 
5 3 6 
1 2 1 
1 3 3 
2 3 1 
4 1 5 
4 5 2 
5 1 2 
【样例输入2】 
5 3 4 
1 2 1 
1 3 3 
2 3 1 
5 1 2

输出

【样例输出1】 
13 M(s) are needed. 
【样例输出2】 
Sth wrong.

备注

对于30%的数据,1≤N≤20   ,   L≤200
对于80%的数据,1≤N≤600   ,   L≤180000
对于100%的数据,1≤N≤1000   ,   1≤M≤N   ,   L≤500000,   1≤a,b≤N   ,   0≤c≤10000。
2010年广州市第二中学初二第二次测试第三题。

思路:

堆优化dij裸求最短路

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<vector>
 6 #include<queue>
 7 #include<algorithm>
 8 #define mx 1001
 9
10 using namespace std;
11 struct orz
12 {
13     int d,p;
14     friend bool operator <(orz a,orz b) {return a.d>b.d;}//堆和set里面都只有小于号,所以要用小根堆的话要将<重定向为>
15 };
16 struct Edge{
17     int to;
18     int w;
19 };
20 priority_queue < orz > ss;
21 int flag = 0,v[mx],d[mx],n,m,l;
22 vector<Edge> edge[mx];
23 void input(){
24     cin>>n>>m>>l;
25     int u,v,wei;
26     Edge test;
27     for(int i = 1;i <= l;i++){
28         scanf("%d%d%d",&u,&v,&wei);
29         test.to = v;
30         test.w = wei;
31         edge[u].push_back(test);
32         test.to = u;
33         edge[v].push_back(test);
34     }
35     for(int i = 0;i < mx;i++) d[i] = 1000000000;
36 }
37 void dij(int s)
38 {
39
40     d[s]=0;
41     orz tmp;
42     tmp.d=0,tmp.p=s;
43     ss.push(tmp);
44     flag++;
45     int x,dd;
46     Edge j;
47     while (!ss.empty())//不能只做n次,要一直做到堆空
48     {
49         tmp=ss.top();
50         ss.pop();
51         x=tmp.p,dd=tmp.d;
52         if (v[x]==flag) continue;//这里一定要判断!!!
53         v[x]=flag;
54         for (int i = 0;i < edge[x].size();i++){
55
56             j = edge[x][i];
57             if (d[j.to]>dd+j.w)
58             {
59                 d[j.to]=dd+j.w;
60                 tmp.d=dd+j.w,tmp.p=j.to;
61                 ss.push(tmp);
62             }
63         }
64
65     }
66 }
67 int main(){
68     input();
69     dij(m);
70     int ans = 0;
71     for(int i = 1;i <= n;i++){
72         if(i == m) continue;
73         if(d[i] >= 1000000000){
74             cout<<"Sth wrong."<<endl;
75             return 0;
76         }
77         ans+=d[i];
78     }
79     cout<<ans<<" M(s) are needed."<<endl;
80     return 0;
81 }

Tyvj 1176 火焰巨魔的惆怅

背景

TYVJ2月月赛第一道

巨魔家族在某天受到了其他种族的屠杀,作为一个英雄,他主动担任了断后的任务,但是,在巨魔家族整体转移过后,火焰巨魔却被困住了,他出逃的方式也只有召唤小火人这一种方式,所以请你帮助他。

描述

我们把火焰巨魔所处的位置抽象成一张有向图,他的位置就是1号点位,目的就是走到第N号点位,因为小火人会裂嘛,所以我们可以看做每走一条路,小火人的数量都会加倍,而每条路上的敌人有多强,会消耗多少小火人c[i]也会给出(c[i]为负值);当然有些时候路上也会遇到魔法泉之类的东西,这时候就可以补充一些小火人咯(c[i]为正值)。如果小火人死光了,那么火焰巨魔也就可以看做是挂了,毕竟智力型英雄就是脆啊。希望你帮助火焰巨魔用最少的初始小火人逃离这次屠杀。

输入格式

第一行两个数N(<=50000),M(<=100000)表示点位数与边数。
一下M行,每行三个数a,b,c表示a,b两点间的边权是c(|c|<=10000)

输出格式

输出仅一个整数,表示最小初始小火人数。

测试样例1

输入

5 4 
1 2 -3 
1 3 -6 
3 4 1 
4 5 -9

输出

4

备注

初始小火人为4个,到3点剩2个,到4变成5个,到5剩1个。
所以初始最少为4,更少的小火人是不足以走到5号点位的。from wsd  TYVJ月赛出题组

思路:

1、由于要求的是从起点到达终点最少出发的小火人,所以是一个路径寻找问题,所以要用到最短路

2、由于小火人最少是1,所以到终点后小火人数量一定是1,否则就必须要在起点派出更多小火人

3、在最短路中,目的是求长度最小,放入队列的必要条件是可以把该点长度变小,所以此题中放入的条件是可以把所需要的火人数量变小

4、从终点开始,做spfa,则由用来松弛的点走到当前节点的最小火人数设为x,则2x + g[now][i] = d[now],可知x可能不为正整数,若为浮点数则向上取整,若x≤0,则将x设为1,然后去比较d[i]进行松弛,最后d[1]便是正确答案

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<queue>
 8 using namespace std;
 9 const int maxn = 100005;
10 const int maxint = ~0U>>1;
11 struct edge{
12     int v;
13     int w;
14 };
15 int n,m,vis[maxn],d[maxn];
16 vector<edge> g[maxn];
17 void input(){
18     cin>>n>>m;
19     int u,v,w;
20     edge tmp;
21     for(int i = 1;i <= m;i++){
22         scanf("%d%d%d",&u,&v,&w);
23         tmp.v = u;
24         tmp.w = w;
25         g[v].push_back(tmp);
26     }
27     for(int i = 1;i <= n;i++){
28         vis[i] = 0;
29         d[i] = maxint;
30     }
31 }
32 void spfa(){
33     queue<int> q;
34     q.push(n);
35     d[n] = 1;
36     vis[n] = 1;
37     int now,to,add;
38     while(!q.empty()){
39         now = q.front();
40         q.pop();
41         vis[now] = 0;
42         for(int i = 0;i < g[now].size();i++){
43             to = g[now][i].v;
44             add = (d[now] - g[now][i].w) >> 1;
45             if((d[now]-g[now][i].w) & 1) add++;
46             if(add <= 0) add = 1;
47             if(d[to] > add){
48                 d[to] = add;
49                 if(!vis[to]){
50                     vis[to] = 1;
51                     q.push(to);
52                 }
53             }
54         }
55     }
56 }
57  int main(){
58     input();
59     spfa();
60     cout<<d[1];
61     return 0;
62 }

时间: 2024-10-08 20:40:38

图论——最短路的相关文章

bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集

bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集 1.这道题我们主要就是要求出距离一个油站的最近的油站 首先我们dijkstra 求出任意一个点到 离他最近的油站的距离 2.然后会发现 如果一条边的两个端点 的最近油站不同的话 那么这条边就会在这两个油站的最短路上 3.然后对于每一条边 我们将他的权值 变为 dis[ u ] + dis[ v ] + e[ i ][ j ] 如果u与v最近油站相同 那么这个无意义 如果不同 那么久表示 u 最近油站 到 v 最近油站的最

POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA)

链接:http://poj.org/problem?id=3259 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BE

HDU 5521 [图论][最短路][建图灵感]

/* 思前想后 还是决定坚持写博客吧... 题意: n个点,m个集合.每个集合里边的点是联通的且任意两点之间有一条dis[i]的边(每个集合一个dis[i]) 求同时从第1个点和第n个点出发的两个人相遇的最短时间,并输出相遇的地点,如果有多个按编号大小顺序输出. 输入: 测试数据 t n m 以下m行每行 dis[i] 该集合点的数量 ...每个点的标号 数据范围: n 2-1e5 所有集合的元素的数量和 1e6 思路: 如果直接跑最短路,边会存爆的. 考虑换种思路建边. 每个集合看作两个点,一

图论 最短路 基础

图论基础 , 最短路 图的简单概念 顶点 (Vertex), 边 (Edge) 有向图 , 无向图 , 无向图是一种特殊的有向图 度,有向图分为出度 和 入度,无向图的度,代表 连出去的边 顶点和边都可以具有属性,称为权重,顶点称为 点权,边 称为 边权 稠密图 边很多,大约是 顶点的平方 稀疏图 边很少 , 重边(平行边),自环, 路径:从一给顶点到达另一个顶点称为一条路径 路径中边的数量称为路径长度,如果路径中的顶点均不重复,称为简单路径 如果路径中的第一个顶点 \(v_i\) 和最后一个顶

洛谷P1027 Car的旅行路线 计算几何 图论最短路

题意 求某城到某城的最小花费 一个城中有四个机场,一个城中的机场相互可达,用公路到达,但是不同城的公路的单位路程的费不同,两个不同城的机场(我不知道相同城可不可以)可以通过机场到达,且飞机单位路程价格一定,问从 a 城到b城的最小花费,可从a的任一机场出发,从 b 的任一机场结束 . 题解 这道题思路还算容易,就是求最短路,只是建图比较麻烦, 总体思路 1.建图(1) 相同城 的四个机场两两连线 求距离, [1]但是他只给出了三个点,也就是说这第四个点要我们自己求 首先他给出三个点,这三个点一定

图论——最短路②

RT 最短路计数 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输出0. 样例 输入: 输出

图论——最短路①

RT 找工就业 Bessie is running out of money and is searching for jobs. Farmer John knows this and wants the cows to travel around so he has imposed a rule that his cows can only make D (1 <= D <= 1,000) dollars in a city before they must work in another

[图论][最短路]步行

题目描述 ftiasch又开发了一个奇怪的游戏,这个游戏是这样的:有N个格子排成一列,每个格子上有一个数字,第i个格子的数字记为Ai.这个游戏有2种操作:1.如果现在在第i个格子,则可以跳到第Ai个格子.2.把某个Ai增加或减少1.nm开始在第1个格子,他需要走到第N个格子才能通关.现在他已经头昏脑涨啦,需要你帮助他求出,从起点到终点最少需要多少次操作. 输入 第1行,1个整数N.第2行,N个整数Ai. 输出 第1行,1个整数,表示最少的操作次数. 样例输入 5 3 4 2 5 3 样例输出 3

[图论]最短路系列

昨天今天两天复习了一下最短路, 1 Floyd 2 Dijkstra 3 Bellman-ford 4 (SPFA) (但是还有一些其他的比如:第k短路,Johnson,差分约束没有仔细研究过) Dijkstra堆优化 luogu3371 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三个整数Fi.Gi.Wi,分别表示第i条有向边的出发点.目标点