迪杰斯特拉(第二种新增点权)

#include<cstdio> //  S-T集合迪杰斯特拉算法理论 
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1000;
const int inf=1000000000;
 
int n,g[maxn][maxn];
int d[maxn],pre[maxn],,weight[maxn],w[maxn];
bool vis[maxn]={false};
// 邻接矩阵版 
void dijkstra(int s){ //s为起点 
	fill(d,d+maxn,inf);  //将到达源点的距离初始化!
	fill(w,w+maxn,0);
	for(int i=0;i<n;i++) pre[i]=i;// ***********更新的地方1  初始化pre! 
	d[s]=0;
	w[s]=weight[s];   //起点到起点的物资数量当然是其自身的物资数量 
	for(int i=0;i<n;i++){  //整体循环n次,通过n步把点加入S集合 
		int u=-1,min=inf;  //u使得d[u]最小,min存放该最小的d[u]; 
		for(int j=0;j<n;j++){  //选出未访问点中到源点距离最小的! 
			if(vis[j]==false&&d[j]<min){
				u=j;  
				min=d[j];
			}
		}
		if(u==-1) return ;
		vis[u]=true;
		for(int v=0;v<n;v++){ //围绕除u以外的各点(被动访问)并比较! 
			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]+weight[v];  //再考虑“开销花费” 
				} else if(d[u]+g[u][v]==d[v] && w[u]+weight[v]>w[v]) { //距离相同时再比较开销花费 
					w[v]=w[u]+weight[v];  //路径最短的情况下,要得到最多的物资! 
				}
				pre[v]=u;//******************更新的地方2 
			}
		}
	}
} //  该核心函数整整 20 行!!!!
//邻接表版 
struct node{
	int v,dis;
};
vector<node> adj[maxn];
void Djkstra(int s){
	fill(d,d+maxn,inf);
	for(int i=0;i<n;i++) pre[i]=i;// ***********11111111111
	d[s]=0;
	for(int i=0;i<n;i++){
		int u=-1,min=inf;
		for(int j=0;j<n;j++){ //d[]可以使用STL的优先队列 复杂度为O(logV) 总复杂度降低为O(VlogV+E)! 
			if(vis[j]==false && d[j]<min){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return ;
		vis[u]=true;
		for(int j=0;j<adj[u].size();j++){ //只有此处与邻接矩阵写法不同! 
			int v=adj[u][j].v; //每个容器内存储的顶点本身就是只有可达的!因此这邻接表 
			if(vis[v]==false && d[u]+adj[u][j].dis<d[v]){//写法比邻接矩阵法更省时间:O(V^2+E)<O(V^2+v^2) 
				d[v]=d[u]+adj[u][j].dis;
				pre[v]=u; //*****************22222222222
			} 
		}	
	}
}  //21行 

void dfs(int s,int v){ //递归——太巧妙了! 
	if(s==v){
		printf("%d ",s);
		return ;
	}
	dfs(s,pre[v]);
	printf("%d ",v);
}


 
int main(){

	
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值