* 题目链接*

描述

南将军统领着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 城市平乱 (最短路)的更多相关文章

  1. nyoj 115 城市平乱

    城市平乱 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...

  2. nyoj 115 城市平乱 dijkstra最短路

    题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=115 dijkstra算法. #include "stdio.h" ...

  3. 南洋理工 OJ 115 城市平乱 dijstra算法

    城市平乱 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...

  4. nyist oj 115 城市平乱 (最短路径)

    城市平乱 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 南将军统领着N个部队.这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安.这M个城市 ...

  5. Nyoj 城市平乱(图论)

    描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M. 现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都 ...

  6. nyoj 115------城市平乱( dijkstra // bellman )

    城市平乱 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...

  7. 城市平乱(Bellman)

    城市平乱 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市 ...

  8. nyoj 115-城市平乱 (BFS)

    115-城市平乱 内存限制:64MB 时间限制:1000ms 特判: No 通过数:5 提交数:8 难度:4 题目描述: 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维 ...

  9. 城市平乱 ---- Dijkstra

    题解 : 以暴乱城市 为 源点 向所有点做最短路径 , 然后检查每个不对到暴乱城市的 最短距离 #include<stdio.h> #include<string.h> #in ...

随机推荐

  1. Flexbox布局模式的理解

    个人博客地址:  雨中的鱼-前端知识分享   http://www.showhtml5.cc    分享干货,有兴趣的人可以一起来分享前端知识  加Q群:440279380   Flexbox,一种C ...

  2. 【廖雪峰老师python教程】——错误和调试

    错误处理 try...except...finally...机制 try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivi ...

  3. Qt Creater 制作汽车仪表盘

    最近项目用到了模拟仪表,网上下载大神编写的按个仪表Meter没有成功 转战 QWt 编译后,在creater中仍然无法使用,只可以在代码中使用 百度说是我编译的版本不对 扔到 开始做自己的 这个用到了 ...

  4. 用Python 的一些用法与 JS 进行类比,看有什么相似?

    Python 是一门运用很广泛的语言,自动化脚本.爬虫,甚至在深度学习领域也都有 Python 的身影.作为一名前端开发者,也了解 ES6 中的很多特性借鉴自 Python (比如默认参数.解构赋值. ...

  5. Go基础篇【第8篇】: 内置库模块 bytes [一]

    bytes包实现了操作[]byte的常用函数.本包的函数和strings包的函数相当类似. func Compare func Compare(a, b []byte) int Compare函数返回 ...

  6. css3 移入移出动画

    css: /*css3 鼠标移入移出动画 底部出现阴影层文字叙述*/ *{;} .div1{width:300px;height: 300px;text-align: center; backgrou ...

  7. nopcommerce商城系统--文档整理

    原址:http://www.nopcommerce.com/documentation.aspx nopCommerce文档可以帮助您一步一步的搭建属于您自己的在线商城.根据该文档说明,您可以选择您想 ...

  8. DPDK Qos之报文处理流水线

    原创翻译,转载请注明出处. 下面是一个支持Qos的复杂报文处理流水线的图: 流水线是通过DPDP可重用的软件库构建出来的.在流水线里实现QoS主要是如下模块:policer,dropper,shced ...

  9. MvcMusicStore学习中常出现的一个BUG

    BUG描述:var genreModel = storeDB.Genres.Include("Albums").Single(g => g.Name == genre); 前 ...

  10. Javascript Array和String的互转换

    Array类可以如下定义: var aValues = new Array(); 如果预先知道数组的长度,可以用参数传递长度 var aValues = new Array(20); -------- ...