* 题目链接*

描述

南将军统领着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. iOS开发中常见的一些异常

    iOS开发中常见的异常包括以下几种NSInvalidArgumentExceptionNSRangeExceptionNSGenericExceptionNSInternallnconsistency ...

  2. 【jQuery】 Ajax

    [jQuery] Ajax $.ajax({ type: "Post", // 发包方式 cache: false, // 是否缓存 contentType: "appl ...

  3. jdk8 新特性stream().map()

    1.大写字符串列表 1.1 简单的Java示例将Strings列表转换为大写 TestJava8.java package com.mkyong.java8; import java.util.Arr ...

  4. jmeter完成CAS登录,并获取token(原创)

    思路: 1.系统完成CAS登录需要验证用户名/密码,以及动态授权参数 2.先通过指定url用正则提取出动态授权参数 3.完成登录需要cookie,需用正则提取出对应的cookie,已完成参数化的自动登 ...

  5. JMeter学习笔记(九) 参数化4--User Variables

    4.User Variables 用户参数 1)线程组右键添加 -> 前置处理器 -> 用户参数 2)配置用户参数 3)添加HTTP请求,引用用户参数,格式: ${} 4)配置线程数 5) ...

  6. js中DOM 节点的一些操作方法

    什么是DOM DOM:文档对象模型.DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构.目的其实就是为了能让js操作html元素而制定的一个规范. DOM就是由节点组成的. 解析过程 ...

  7. thinkPHP form表单提交参数无法获取

    后台打印获取的数据为empty, 找了半天,是因为 input标签没有写name, 真是醉了!记一下,免得以后再犯错了.

  8. ASP.NET 概述

    https://msdn.microsoft.com/zh-cn/library/4w3ex9c2(VS.100).aspx ASP.NET 概述 更新:2007 年 11 月 ASP.NET 是一个 ...

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

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

  10. 微信小程序—setTimeOut定时器的坑

    原文地址: http://fanjiajia.cn/2018/06/27/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E2%80%94setTimeOu ...