PAT A1003

今天也是为了cc,努力奋斗的一天ヾ(≧▽≦*)o

疑问

暂无

代码——Dijkstra版

#include<stdio.h>

#include<algorithm>

using namespace std;
 
//最大的点的数量 
const int MAXV = 1010;
//定义不可达时的距离 
const int INF = 1000000000;

//输入节点数 
int n; 
//源点s
int s;
//终点t
int t; 
//无向图G
int G[MAXV][MAXV];
//标记是否访问数组
bool vis[MAXV] = {false};
//单源最短路径数组
int d[MAXV];
//单源最短路径条数数组
int num[MAXV] = {0};
//救援数rescue数组
int r[MAXV]={0}; 
//单源最短路径最大救援数数组
int maxr[MAXV]={0};

//单源最短路径Dijkstra算法
void Dijkstra(){
	//1.初始化操作 
	//首先,数组d[MAXV]中的单源最短路径设置为INF 
	fill(d,d+MAXV,INF);
	
	//将起点s到自己的距离设置为0
	d[s] = 0;
	
	//将起点s的路径数设置为1
	num[s] = 1;
	
	//将起点s的单源最短路径最大救援数设置为它的初始值 
	maxr[s] = r[s]; 
	
	for(int i=0;i<n;i++){
		
		//2.求最近的点 
		int u = -1;
		int MIN = INF;
		
		for(int j=0;j<n;j++){
			if(vis[j] == false && d[j] != INF && d[j] < MIN){
				u = j;
				MIN = d[j];
			}
		}
		
		//设置最近的点已经被访问 
		vis[u] = true;
		
		//如果u还是-1,说明存在不相连的点,则退出循环 
		if(u == -1){
			return;
		} 
		
		//3.对d[v]进行更新
		for(int v=0;v<n;v++){
			if(vis[v] == false && G[u][v] != INF){
				if(G[u][v] + d[u] < d[v]){
					d[v] = G[u][v] + d[u];
					num[v] = num[u];
					maxr[v] = r[v] + maxr[u];
				}else if(G[u][v] + d[u] == d[v]){
					num[v] += num[u];
					if(maxr[v] < r[v] + maxr[u]){
						maxr[v] = r[v] + maxr[u];
					}
				}
			}
		} 
	}
	
	printf("%d %d",num[t],maxr[t]);
} 

 
int main(){
	//numberOfRoads
	int nor;
	scanf("%d %d %d %d",&n,&nor,&s,&t);
	
	
	//初始化图G
	fill(G[0],G[0]+MAXV*MAXV,INF);
	 
	for(int i=0;i<n;i++){
		scanf("%d",&r[i]);
	}
	
	for(int i=0;i<nor;i++){
		int a,b,c;
		scanf("%d %d %d",&a,&b,&c);
		G[a][b] = c;
		G[b][a] = c;
	}	
	
	Dijkstra();

	return 0;
}

代码——Bellman-Ford版

#include<stdio.h>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;

const int MAXV = 510;
const int INF = 1000000000;

struct Node{
	int v;
	int dis;
};

//顶点的数量 
int n;
//边的数量 
int m;
//起点
int s;
//终点
int t;
//邻接表
vector<Node> Adj[MAXV];
//存放最短路径的数组
int d[MAXV];
//存放每个点的权重的数组
int weight[MAXV]; 
//存放最大权重的数组 
int w[MAXV];
//存放前驱节点
set<int> pre[MAXV]; 
//存放最短路径的个数 
int num[MAXV]; 

bool Bellman(int s){
	fill(d,d+MAXV,INF);
	fill(w,w+MAXV,0);
	fill(num,num+MAXV,0);
	
	d[s] = 0;
	w[s] = weight[s];
	num[s] = 1;
	
	for(int i=0;i < n-1;i++){
		for(int u=0;u < n;u++){
			for(int j=0;j<Adj[u].size();j++){
				int v= Adj[u][j].v;
				int dis = Adj[u][j].dis;
				if(d[u] + dis < d[v]){
					d[v] = d[u] + dis;
					pre[v].clear();
					pre[v].insert(u);
					num[v] = num[u];
					w[v] = w[u] + weight[v];
				}else if(d[u] + dis == d[v]){
					pre[v].insert(u);
					num[v] = 0;
					for(set<int>::iterator it = pre[v].begin();it != pre[v].end();it++){
						num[v] += num[*(it)];
					}
					if(w[u] + weight[v] > w[v]){
						w[v] = w[u] + weight[v];
					}
				}	
			}
		}
	}
	
	for(int u=0;u<n;u++){
		for(int j=0;j<Adj[u].size();j++){
			int v = Adj[u][j].v;
			int dis = Adj[u][j].dis;
			if(d[u] + dis < d[v]){
				return false;
			} 
		}
	}
	
	printf("%d %d",num[t],w[t]);
	return true;
}
 
int main(){
	scanf("%d %d %d %d",&n,&m,&s,&t);
	
	for(int i=0;i<n;i++){
		scanf("%d",&weight[i]);
	}
	
	for(int i=0;i<m;i++){
		int x,y,z;
		scanf("%d %d %d",&x,&y,&z);
		Node n1;
		Node n2;
		n1.v = x;
		n1.dis = z;
		n2.v = y;
		n2.dis = z;
		
		Adj[x].push_back(n2);
		Adj[y].push_back(n1);
	}
	
	Bellman(s);
	
	return 0;
} 

反思

  1. 忘记对邻接矩阵G[MAXV][MAXV]进行初始化了,然后。。。发现了也不知道该怎么初始化,2333,《算法笔记》上对二维数组的初始化,我受教了:fill(G[0],G[0]+MAXV*MAXV,INF)
  2. 感觉这个Dijkstra其实还好,只要理解了伪代码,自己写起来还是比较容易的;
  3. 这道题目比较综合,不是“裸”的Dijkstra,加入了点权最短路径数量,比较综合,值得一做,做一道题,训练三个点,爽呀~~~~
  4. 集合的遍历,可以使用迭代器进行,我又忘记了,呜呜呜:
    for(set<int>::iterator it = pre[v].begin();it != pre[v].end();it++){
    	num[v] += *(it);
    }
    
  5. 集合set使用迭代器遍历时,不能使用it < pre[v].end(),只能使用it != pre[v].end
  6. 集合set清空操作为clear()
  7. 结构体的构造函数:
struct Node{
	int v,dis;
	Node(int _v,int _dis) : v(_v),dis(_dis) {}
}

参考文档

算法笔记

发布了15 篇原创文章 · 获赞 0 · 访问量 217

猜你喜欢

转载自blog.csdn.net/yc_cy1999/article/details/103933692