NYOJ 115 城市平乱 (最短路)
描述
南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市。
他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M。
现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都派遣了一个分队沿最近路去往暴乱城市平乱。
现在已知在任意两个城市之间的路行军所需的时间,你作为南将军麾下最厉害的程序员,请你编写一个程序来告诉南将军第一个分队到达叛乱城市所需的时间。
注意,两个城市之间可能不只一条路。
- 输入
第一行输入一个整数T,表示测试数据的组数。(T<20)每组测试数据的第一行是四个整数N,M,P,Q(1<=N<=100,N<=M<=1000,M-1<=P<=100000)其中N表示部队数,M表示城市数,P表示城市之间的路的条数,Q表示发生暴乱的城市编号。随后的一行是N个整数,表示部队所在城市的编号。再之后的P行,每行有三个正整数,a,b,t(1<=a,b<=M,1<=t<=100),表示a,b之间的路如果行军需要用时为t数据保证暴乱的城市是可达的。 - 输出
对于每组测试数据,输出第一支部队到达叛乱城市时的时间。每组输出占一行 - 样例输入
1
3 8 9 8
1 2 3
1 2 1
2 3 2
1 4 2
2 5 3
3 6 2
4 7 1
5 7 3
5 8 2
6 8 2 - 样例输出
4
分析:
这是一道求解最短路的问题,因为图中的权值没有涉及到负权值的情况,所以用迪杰斯特拉和spfa都能写(如果有负权值的话,迪杰斯特拉就不能用了,只能用spfa)。
说一下迪杰斯特拉和spfa的一些小区别吧,在存储图的时候呢,迪杰斯特拉是用邻接矩阵的方式,而spfa则是用邻接表的方式,这样就能够看出来在访问与某一个点相连的路径的时候(如果数据范围比较大的话),spfa要比迪杰斯特拉快的多,事实上也是如此,还有需要说明的一点就是能用迪杰斯特拉写的题全部都能用spfa写。
然后具体的看一下迪杰斯特拉和spfa算法:
迪杰斯特拉算法:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
int Tu[1002][1002];///存储图的信息
int dis[1002];///到源点的最短距离
int bj[1002];///标记这个点有没有访问过
int jun[1002];///标记军队所在的城市
int N,M,P,Q;
void init()///数据的初始化
{
memset(jun,0,sizeof(jun));
for(int i=1; i<=M; i++)
for(int j=1; j<=M; j++)
{
if(i==j)
Tu[i][j]==0;
else
Tu[i][j]=INF;
}
}
int dij()///迪杰斯特拉算法
{
int sum=0;
for(int i=1; i<=M; i++)
{
dis[i]=Tu[Q][i];///到i点的最短距离
bj[i]=0;///标记这个点有没有访问过
}
bj[Q]=1;///1点访问过了
int flag=Q;///下一个起始点
int cut=1;///城市的个数
while(cut<M)
{
int Min=INF;
for(int i=1; i<=M; i++)
{
if(bj[i]==0&&dis[i]<Min)///找到下一个最短距离
{
Min=dis[i];
flag=i;
}
}
bj[flag]=1;///标记flag点访问过
cut++;///城市个数加
for(int i=1; i<=M; i++)
if(bj[i]==0&&dis[i]>dis[flag]+Tu[flag][i])///这个点没有访问过并且最短距离可以更新
{
dis[i]=dis[flag]+Tu[flag][i];
}
}
int Min=INF;
for(int i=1; i<=M; i++)///求出最小值
{
if(jun[i]==1)
{
if(dis[i]<Min)
Min=dis[i];
}
}
return Min;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&N,&M,&P,&Q);
init();
int a,b,c;
while(N--)
{
scanf("%d",&a);
jun[a]=1;
}
while(P--)
{
scanf("%d%d%d",&a,&b,&c);
Tu[a][b]=Tu[b][a]=min(Tu[a][b],c);///可能会存在重复输入路径的情况
}
printf("%d\n",dij());
}
return 0;
}
在用邻接矩阵存储图的时候,可以动态的申请vector数组来模拟,也可以直接用数组来模拟,两种方法在思路上是完全一样的,不同之处在于时间,vector在插入元素的时候,用push_back(),在数据较多的时候是比较浪费时间的,而用数组模拟的话,有一个头插法的思想,会节省时间。
spfa算法(vector):
#include<stdio.h>
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
int N,M,P,Q;
int jun[1002];
int Time[1002][1002];
int dis[1002];
int bj[1002];
vector<int>v[1002];
void init()
{
memset(jun,0,sizeof(jun));
memset(v,0,sizeof(v));
for(int i=0; i<=M; i++)
for(int j=1; j<=M; j++)
{
if(i==j)
Time[i][j]=0;
else
Time[i][j]=INF;
}
}
int spfa()
{
for(int i=1; i<=M; i++)
{
dis[i]=INF;
bj[i]=0;
}
dis[Q]=0;
queue<int>q;
q.push(Q);
bj[Q]=1;
int flag;
while(!q.empty())
{
flag=q.front();
q.pop();
bj[flag]=0;
for(int i=0; i<v[flag].size(); i++)
{
int t=v[flag][i];
if(dis[t]>dis[flag]+Time[flag][t])
{
dis[t]=dis[flag]+Time[flag][t];
if(bj[t]==0)
{
bj[t]=1;
q.push(t);
}
}
}
}
int Min=INF;
for(int i=1; i<=M; i++)
{
// printf("dis %d\n",dis[i]);
if(jun[i]==1)
{
if(dis[i]<Min)
Min=dis[i];
}
}
return Min;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&N,&M,&P,&Q);
init();
int a,b,c;
while(N--)
{
scanf("%d",&a);
jun[a]=1;
}
while(P--)
{
scanf("%d%d%d",&a,&b,&c);
v[a].push_back(b);
v[b].push_back(a);
Time[a][b]=c;
Time[b][a]=c;
}
printf("%d\n",spfa());
}
return 0;
}
spfa算法(数组):
#include<stdio.h>
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
int N,M,P,Q,cnt;
int jun[1002];///标记军队所在的城市
int dis[1002];///到源点的距离
int bj[1002];///标记这个点有没有访问过
int head[1002];///头节点
struct Node
{
int to;///相邻的下一个点
int w;///权值
int pre;///前一条边
} node[100002];
void add(int a,int b,int c)
{
node[cnt].to=b;
node[cnt].w=c;
node[cnt].pre=head[a];///采用头插法的思想,给他们的前一条边赋值
head[a]=cnt;
cnt++;
}
void init()///初始化
{
memset(jun,0,sizeof(jun));
memset(head,-1,sizeof(head));
memset(node,0,sizeof(node));
}
int spfa( )
{
for(int i=1; i<=M; i++)
{
dis[i]=INF;
bj[i]=0;
}
dis[Q]=0;
queue<int>q;
q.push(Q);
bj[Q]=1;
int flag;
while(!q.empty())
{
flag=q.front();
q.pop();
bj[flag]=0;
for(int i=head[flag]; i!=-1; i=node[i].pre)///访问所有的与它相连的边
{
int t=node[i].to;
if(dis[t]>dis[flag]+node[i].w)
{
dis[t]=dis[flag]+node[i].w;
if(bj[t]==0)
{
bj[t]=1;
q.push(t);
}
}
}
}
int Min=INF;
for(int i=1; i<=M; i++)
{
// printf("dis %d\n",dis[i]);
if(jun[i]==1)
{
if(dis[i]<Min)
Min=dis[i];
}
}
return Min;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cnt=0;
scanf("%d%d%d%d",&N,&M,&P,&Q);
init();
int a,b,c;
while(N--)
{
scanf("%d",&a);
jun[a]=1;
}
while(P--)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
printf("%d\n", spfa());
}
return 0;
}
NYOJ 115 城市平乱 (最短路)的更多相关文章
- nyoj 115 城市平乱
城市平乱 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...
- nyoj 115 城市平乱 dijkstra最短路
题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=115 dijkstra算法. #include "stdio.h" ...
- 南洋理工 OJ 115 城市平乱 dijstra算法
城市平乱 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...
- nyist oj 115 城市平乱 (最短路径)
城市平乱 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描写叙述 南将军统领着N个部队.这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安.这M个城市 ...
- Nyoj 城市平乱(图论)
描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M. 现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都 ...
- nyoj 115------城市平乱( dijkstra // bellman )
城市平乱 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...
- 城市平乱(Bellman)
城市平乱 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...
- nyoj 115-城市平乱 (BFS)
115-城市平乱 内存限制:64MB 时间限制:1000ms 特判: No 通过数:5 提交数:8 难度:4 题目描述: 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维 ...
- 城市平乱 ---- Dijkstra
题解 : 以暴乱城市 为 源点 向所有点做最短路径 , 然后检查每个不对到暴乱城市的 最短距离 #include<stdio.h> #include<string.h> #in ...
随机推荐
- Extjs报错:isField为空或不是对象
在做Extjs开发的时候,有时候会碰到一个奇怪的问题,就是报错说"isField为空或不是对象",经过调试发现是一个数组,显示的长度是21,但是数组里面的个数只有 ...
- TFS权限配置
装了TFS,要给TFS里添加用户,然后分配权限.其实一般项目中权限都不会控制的那么细,所以就直接想给项目组的每个人建一个用户,让他们都能访问这个项目的代码并进行任何操作.只想怎么简单怎 ...
- jmeter常用的内置变量
1. vars API:http://jmeter.apache.org/api/org/apache/jmeter/threads/JMeterVariables.html vars.get(& ...
- 【个人训练】(UVa11129)An antiarithmetic permutation
题意与解析 一条非常有趣的二分题.一开始没有懂解法,去网上看了半天全是做法没有这样做为什么是对的(或者说的很含糊).一做完回顾一下立刻有点开朗的感觉. 题意很简单,维护一个0-n-1的数列,使其选出长 ...
- Python 3基础教程23-多维列表
这里简单举例一个多维列表,多维看起来都很晕. # 多维列表 x = [ [5,6],[6,7],[7,2] ,[2,5] ,[4,9]] print(x) # 根据索引引用列表元素,例如打印[6,7] ...
- python接口测试(三)——Excell文件读取进行参数化
python进行http请求时,需要对参数进行参数化,此时就可以运用Excel进行,具体如下: 1.梳理出请求中那些参数需要参数化,然后新建一个Excel,如图: 2.读取Excel中的内容,在读取前 ...
- python学习总结----内置函数及数据持久化
抽象基类(了解) - 说明: - 抽象基类就是为了统一接口而存在的 - 它不能进行实例化 - 继承自抽象类的子类必须实现抽象基类的抽象方法 - 示例: from abc import ABC, abs ...
- 孤荷凌寒自学python第七十五天开始写Python的第一个爬虫5
孤荷凌寒自学python第七十五天开始写Python的第一个爬虫5 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 直接上代码.详细过程见文末屏幕录像 ...
- 【转】GOOGLE-PROTOBUF与FLATBUFFERS数据的序列化和反序列化
转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/unity3d-game/1607.html 关于Protobuf 通过本文的转载和分享的相关链接,足够 ...
- ASP.NET页面之间传值Application(5)
Application对象的作用范围是整个全局,也就是说对所有用户都有效.它在整个应用程序生命周期中都是有效的,类似于使用全局变量一样,所 以可以在不同页面中对它进行存取.它和Session变量的区别 ...