1003 Emergency (25 分)

版本3

标记一下几个易错点。

  1. 在Dijkstra函数中没有标记使用过的顶点
  2. 在Dijkstra函数中没有更新最短距离
  3. 在DFS中没有return
  4. 在DFS中递归是对pre[s]向量
#include <cstdio>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <algorithm> 
#include <unordered_set>
#include <unordered_map>
#include <map>
using namespace std;
int n, m, S, D;
const int N = 505;
const int INF = 0x3f3f3f3f;
int dot[N], d[N];
int G[N][N];
bool vis[N];
vector<int> pre[N], temp;
int opt = -1, num = 0;
void Dijkstra(){
	memset(d, 0x3f, sizeof d);
	memset(vis, 0, sizeof vis);
	d[S] = 0;
	for(int i = 0; i < n; i++){
		int u = -1;
		for(int j = 0; j < n; j++){
			if(!vis[j] &&(u == -1 || d[j] < d[u])) u = j;
		}
		vis[u] = true;  //1.标记使用过的顶点
		for(int j = 0; j < n; j++){
			if(!vis[j]){
				if(G[u][j] + d[u] < d[j]){
					d[j] = G[u][j] + d[u]; //2. 更新距离 
					pre[j].clear();
				}
				if(G[u][j] + d[u] == d[j]){
					pre[j].push_back(u);
				}
			}
		}
	}
}

void DFS(int s){
	if(s == S){
		temp.push_back(s);
		int t = 0;
		num++;
		for(auto it: temp){
			t += dot[it];
		}
		if(t > opt) {
			opt = t;
		}
		temp.pop_back();
		return;  //3.记得返回
	}
	temp.push_back(s);
	for(int i = 0; i < pre[s].size(); i++){
		DFS(pre[s][i]); //4.对pre向量递归
	}
	temp.pop_back();
}
int main(){
	int u, v, w;
	scanf("%d%d%d%d", &n, &m, &S, &D);
	memset(G, 0x3f, sizeof G);
	for(int i= 0; i < n; i++) scanf("%d", &dot[i]);
	while(m--){
		scanf("%d %d %d", &u, &v, &w);
		G[u][v] = w;
		G[v][u] = w;
	}
	Dijkstra();
	DFS(D);
	cout<<num<<" "<<opt<<endl;

	return 0;
}

版本2

#include<bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF = 1e9+5;
int N,M,C1,C2,c1,c2,L;
int weights[maxn],w[maxn]; //点权值  和 每个顶点的最大点权 
int G[maxn][maxn];   //邻接矩阵图 
int d[maxn],num[maxn]; //d数组数最短路径  num数组是最短路径的数量 
bool vis[maxn]={false};
void Dijkstra(int s){
	fill(d,d+N,INF); //初始化最短距离为无穷
	d[s] = 0;  //起点的最短路径为0
	num[s]=1;
	w[s] = weights[s];
	for(int i=0;i<N;i++){
		int u = -1, Min=INF;
		for(int j=0;j<N;j++){
			if(vis[j]==false && d[j] < Min){ //没被访问过,且有最短路径,则挑选出来 
				Min = d[j];
				u = j;
			}
		}
		vis[u]=true;
		for(int v=0;v<N;v++){
			if(vis[v]==false && G[u][v]!=INF){
				if(d[u] + G[u][v] < d[v]){  //最短路径更新 
					d[v]=d[u] + G[u][v];    //路径最短 
					w[v]=w[u] + weights[v]; //点权最大 
					num[v] = num[u];  //路径数量没有增加,则顺延 
				}else if(d[u] + G[u][v] == d[v]){
					num[v] += num[u]; //路径数量增加
					if(w[u] + weights[v] > w[v]){
						w[v]=w[u] + weights[v];
					} 
				} 
			}
		} 
	}  
	
}
int main(){
	fill(G[0],G[0]+maxn*maxn,INF); //没有边的地方就为无穷大 
	scanf("%d%d%d%d",&N,&M,&C1,&C2);
	for(int i=0;i<N;i++){
	 	scanf("%d",&weights[i]); //保存点权 
	 }
	for(int i=0;i<M;i++){
		scanf("%d%d%d",&c1,&c2,&L);
		G[c1][c2]=L;  //路为无向图 
		G[c2][c1]=L;
	}
	Dijkstra(C1);
	printf("%d %d\n",num[C2],w[C2]);
	return 0;
}

版本1

Dijkstra + DFS

#include<bits/stdc++.h>
#include<vector>
using namespace std;
const int maxn=505;
const int INF = 1e9+5;
int N,M,C1,C2,c1,c2,L;
int weights[maxn]; //点权值  
int G[maxn][maxn];   //邻接矩阵图 
int d[maxn]; //d数组数最短路径  
bool vis[maxn]={false};
vector<int> pre[maxn];
void Dijkstra(int s){
	fill(d,d+N,INF); //初始化最短距离为无穷
	d[s] = 0;  //起点的最短路径为0
	for(int i=0;i<N;i++){
		int u = -1, Min=INF;
		for(int j=0;j<N;j++){
			if(vis[j]==false && d[j] < Min){ //没被访问过,且有最短路径,则挑选出来 
				Min = d[j];
				u = j;
			}
		}
		vis[u]=true;
		for(int v=0;v<N;v++){
			if(vis[v]==false && G[u][v]!=INF){
				if(d[u] + G[u][v] < d[v]){  //最短路径更新 
					d[v]=d[u] + G[u][v];    //路径最短 
					pre[v].clear();
					pre[v].push_back(u);  //有最优前驱,先清空 
				}else if(d[u] + G[u][v] == d[v]){
					pre[v].push_back(u);  //有重复最短路径,直接添加 
				} 
			}
		} 
	}  
	
}
int optvalue,total=0;
vector<int> path,tempPath;
void DFS(int v){ //递归式+边界
	if(v==C1){   //叶子节点 即起点  因为是倒着找回去的 最开始给的是终点 
		total++;
		tempPath.push_back(v);
		int dotvalue=0;  //点权
		for(int i=tempPath.size()-1;i >=0; i--){
			int id=tempPath[i];
			dotvalue += weights[id];  
		}
		if(dotvalue > optvalue) {
			optvalue = dotvalue;
			path.clear();
			for(int i=tempPath.size()-1;i >=0; i--){
				path.push_back(tempPath[i]);
			}
		}
		tempPath.pop_back();  
		return;   //终止条件 
	} 
	tempPath.push_back(v);
	for(int i=0;i<pre[v].size();i++){ //遍历pre[v]的所有结点并进行递归 
		DFS(pre[v][i]);
	} 
	tempPath.pop_back();
	
}
int main(){
	fill(G[0],G[0]+maxn*maxn,INF); //没有边的地方就为无穷大 
	scanf("%d%d%d%d",&N,&M,&C1,&C2);
	for(int i=0;i<N;i++){
	 	scanf("%d",&weights[i]); //保存点权 
	 }
	for(int i=0;i<M;i++){
		scanf("%d%d%d",&c1,&c2,&L);
		G[c1][c2]=L;  //路为无向图 
		G[c2][c1]=L;
	}
	Dijkstra(C1);
	DFS(C2);
	printf("%d %d\n",total,optvalue);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值