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 ...
随机推荐
- you need to resolve your current index first 已解决
从一个分支A切换到另一个分支B后,对切换后的B分支进行pull操作,因为pull操作实际上包含了fetch+merge操作,在执行 merge操作时,由于很长时间没有对B分支执行过pull/merge ...
- 装机、UEFI双系统安装
装机设置 设置默认中图标显示查看-选项-查看-应用到文件夹 控制面板-语言-管理输入法 word-选项-取消输入法设置处于活动状态word-字体-设置默认值 高DPI的显示屏,需要使用125%的缩放, ...
- Tensorflow多线程输入数据处理框架
Tensorflow提供了一系列的对图像进行预处理的方法,但是复杂的预处理过程会减慢整个训练过程,所以,为了避免图像的预处理成为训练神经网络效率的瓶颈,Tensorflow提供了多线程处理输入数据的框 ...
- [boost-2] 智能指针
boost库学习: 智能指针: shared_ptr指针,定义在boost::shared_ptr,如果开发环境支持的话,可以使用memory中的std::shared_ptr. shared_ptr ...
- @section script{}的使用
1,MVC视图中,JS代码被放在下面的Razor代码中(@section script{}) 2,这样做的好处是:在视图进行JS编码时是一个很好 的实践,在共享视图(_layout.cshtml),存 ...
- beta版本冲刺四
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组 ...
- Java开发环境配置时的dt.jar与tools.jar是什么(转载)
你了解dt.jar吗 很多人在初学Java的时候,都要配置环境变量.在配置CLASSPATH的时候,都会加上一个当前目录.,还有两个jar:dt.jar和tools.jar.其实好多人都不了解这两个j ...
- 在es中用scroll查询与completableFuture
一般而言,es返回数据的上限是10000条,如果超过这个数量,就必须使用scroll查询. 所谓scroll查询就类似DBMS中的游标,或者快照吧,利用查询条件,在第一次查询时,在所有的结果上形成了一 ...
- Intellij IDEA将工程打包成jar包并执行
打开File -> Project Structure -> Artifacts 点击“+”,选择“Jar”,选择Empty或From modules with dependencies, ...
- sessionStorage的用法总结
sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁.因此sessionStorage不是一种持久化的本地 ...