NYOJ 115-城市平乱(最短路径 dijkstra / spfa)

题目描述:

南将军统领着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

模拟题目信息,从s[i]出发。 

#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;

int t,n,m,p,q;
int mp[1010][1010];
int s[1010];
int vis[1010];
int dis[1010];
bool book[1010];
 
void dijkstra(int u){
	
	memset(dis,INF,sizeof(dis));
	memset(book,0,sizeof(book));
	int start = u;
	book[start] = true;
	
	for(int i = 1; i <= m; i++){
		dis[i] = min(dis[i],mp[start][i]);
		
	}
	for(int i = 1; i <= m; i++){
		int minm = INF;
		for(int j = 1; j <= m; j++){
			if(!book[j] && minm > dis[j]){
				minm = dis[start = j];
			}
		}
		book[start] = true;
		for(int j = 1; j <= m; j++){
			dis[j] = min(dis[j], dis[start] + mp[start][j]);
		}
	}
}

int main(){
	cin>>t;
	while(t--){
		memset(mp,INF,sizeof(mp));
		memset(s,0,sizeof(s));
		scanf("%d%d%d%d",&n ,&m ,&p ,&q);
		for(int i = 1; i <= n; i++){
			scanf("%d",&s[i]);
		}
		int u, v, c;
		for(int i = 0; i < p; i++){
			scanf("%d%d%d",&u ,&v ,&c);
			mp[u][v] = mp[v][u] = c;
		}
		
		int Min =INF;
		for(int i = 1; i <= n; i++){
			dijkstra(s[i]);
			Min = min(Min,dis[q]);
		}
		cout<

反向模拟,从q点出发。 

 

#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;

int t,n,m,p,q;
int mp[1010][1010];
int s[1010];
int dis[1010];
bool book[1010];
 
int dijkstra(){
	int Min =INF;
	memset(dis,INF,sizeof(dis));
	memset(book,0,sizeof(book));
	int start = q;
	book[start] = true;
	
	for(int i = 1; i <= m; i++){
		dis[i] = min(dis[i],mp[start][i]);
	}
	
	for(int i = 1; i <= m; i++){
		int minm = INF;
		for(int j = 1; j <= m; j++){
			if(!book[j] && minm > dis[j]){
				minm = dis[start = j];
			}
		}
		book[start] = true;
		for(int j = 1; j <= m; j++){
			dis[j] = min(dis[j], dis[start] + mp[start][j]);
		}
	}
	
	for(int i =1; i <= n; i++){
		Min = min(Min,dis[s[i]]);
	}
	return Min;
}

int main(){
	cin>>t;
	while(t--){
		memset(mp,INF,sizeof(mp));
		memset(s,0,sizeof(s));
		scanf("%d%d%d%d",&n ,&m ,&p ,&q);
		for(int i = 1; i <= n; i++){
			scanf("%d",&s[i]);
		}
		int u, v, c;
		for(int i = 0; i < p; i++){
			scanf("%d%d%d",&u ,&v ,&c);
			mp[u][v] = mp[v][u] = c;
		}
		
		cout<

spfa 时间复杂度小

原理是队列优化时间复杂度,vector邻接表优化空间复杂度

#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define maxn 1010
using namespace std;
int n,V,E,q;
struct node{
	int v, c;
};
vector mp[maxn];
bool vis[maxn];
int d[maxn];
int s[110];

void spfa(int u){
	queue que;
	for(int i = 1; i <= V; i++)	d[i] = inf;
	memset(vis,false,sizeof(vis));
	d[u] = 0,vis[u] = true;
	que.push(u);
	while(!que.empty()){
		u = que.front(); que.pop();
		for(int i = 0; i < mp[u].size(); i++){
			int v = mp[u][i].v;
			int c = mp[u][i].c;
			if(d[v] > d[u] + c){
				d[v] = d[u] +c;
				if(!vis[v]){
					vis[v] = true;
					que.push(v);
				}
			}
		}
		vis[u] = false;
	}
}
int main(){
	int T;
	cin>>T;
	while(T--){
		cin>>n>>V>>E>>q;
		for(int i = 1; i <= V; i++){
			mp[i].clear();
		}
		for(int i = 0; i < n; i++){
			cin>>s[i];
		}
		int a ,b, c ;
		for(int i = 0 ; i < E; i++){
			node t;
			cin>>a>>b>>c;
			t.v = b, t.c =c;
			mp[a].push_back(t);
			t.v = a;
			mp[b].push_back(t);
		}
		spfa(q);
		int ans = inf;
		for(int i = 0; i < n; i++){
			ans = min(ans,d[s[i]]);
		}
		cout<

 

你可能感兴趣的:(学习,图论)