堆优化dij

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define maxn 110        //最大顶点个数
#define INF 0xffffff    //权值上限
int w[maxn][maxn];      //邻接矩阵,存储权值
int n;                  //顶点个数

struct node             //顶点节点,保存id和到源顶点的估算距离,优先队列需要的类型
{
	int id, weight;     //源顶点id和估算距离
	friend bool operator<(node a, node b)   //因要实现最小堆,按升序排列,因而需要重载运算符,重定义优先级,以小为先
	{
		return a.weight > b.weight;
		//priority_queue的排序比较函数和我们的观念相反. priority_queue一般就是用堆做的,默认是用less比较实现的大根堆,
		//比如当先维护堆,从父结点A开始下降整理堆,它会用A的孩子B与A调用less<>对象假设名字叫cmp,会这样传参,
		//if(cmp(A,B)){那么调换A,B结点值} ,less里肯定是 return A<B; 所以我们想要实现小根堆,在传参次序为(A,B)的情况下,
		//只能修改比较函数cmp,如果A<B,返回false,A>B才返回真.
	}
};
priority_queue<node> q;     //优先队列,最小堆,实现Dijkstra的重要数据结构,用stl实现
int parent[maxn];           //每个顶点的父亲节点,可以用于还原最短路径树
bool visited[maxn];         //用于判断顶点是否已经在最短路径树中,或者说是否已找到最短路径
node d[maxn];               //源点到每个顶点估算距离,最后结果为源点到所有顶点的最短路。
void Dijkstra(int s)        //Dijkstra算法,传入源顶点
{
	for(int i = 1; i <= n; i++)     //初始化
	{
		d[i].id = i;
		d[i].weight = INF;          //估算距离置INF
		parent[i] = -1;             //每个顶点都无父亲节点
		visited[i] = false;
	}
	d[s].weight = 0;                //源点到源点最短路权值为0
	q.push(d[s]);                   //压入队列中
	while(!q.empty())               //算法的核心,队列空说明完成了操作
	{
		node cd = q.top();          //取最小估算距离顶点
		q.pop();
		int u = cd.id;
		if(visited[u])
			continue;
		visited[u] = true;
				//松弛操作
	for(int v = 1; v <= n; v++) //找所有与他相邻的顶点,进行松弛操作,更新估算距离,压入队列。
	{
		if(v != u && !visited[v] && d[v].weight > d[u].weight+w[u][v])
		{
			d[v].weight = d[u].weight+w[u][v];
			parent[v] = u;
			q.push(d[v]);
		}
	}
	}
}
int main()
{
     int m, a, b, c, st, ed;
     scanf("%d%d", &n, &m);
     for(int i = 1; i <= n; i++)     //邻接矩阵存储前需要初始化
         for(int j = i; j <= n; j++)
             w[i][j] = w[j][i] = INF;
     while(m--)
     {
         scanf("%d%d%d", &a, &b, &c);
         if(w[a][b] > c)
             w[a][b]= w[b][a] = c;
     }
     scanf("%d%d", &st, &ed);
     Dijkstra(st);
     if(d[ed].weight != INF)
         printf("最短路径权值为:%d\n", d[ed].weight);
     else
		printf("不存在从顶点%d到顶点%d的最短路径。\n", st, ed);
	 return 0;
}

 以上为dij

https://blog.csdn.net/scutbenson/article/details/81320460

以上为spfa

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define maxn 110        //最大顶点个数
#define INF 0xffffff    //权值上限
int w[maxn][maxn];      //邻接矩阵,存储权值
int n;                  //顶点个数
typedef pair<int,int> p1;
priority_queue< p1,vector<p1>,greater<p1> >q;    //优先队列,对于pair类型数据,默认的是按照第一个域的大小来建堆,所以不用重载运算符。
int parent[maxn];           //每个顶点的父亲节点,记录路径
bool visited[maxn];         //用于判断顶点是否已经在最短路径树中,或者说是否已找到最短路径
int d[maxn];               //源点到每个顶点估算距离,最后结果为源点到所有顶点的最短路。
void Dijkstra(int s)        //Dijkstra算法,传入源顶点
{
	for(int i = 1; i <= n; i++)     //初始化
	{
	
		d[i] = INF;          //估算距离置INF
		parent[i] = -1;             //每个顶点都无父亲节点
		visited[i] = false;
	}
	d[s]= 0;                //源点到源点最短路权值为0
	q.push(make_pair(d[s],s));
	while(!q.empty())               //算法的核心,队列空说明完成了操作
	{
		p1 cd = q.top();          //取最小估算距离顶点
		q.pop();
		int u = cd.second;
		if(visited[u])
			continue;//很重要,因为在松弛的过程中u点肯定多次进堆,所以弹堆时候再遇见u直接弹就可以,因为最小的d[u],已经求出并且出堆。
		visited[u] = true;
				//松弛操作
	for(int v = 1; v <= n; v++) //找所有与他相邻的顶点,进行松弛操作,更新估算距离,压入队列。
	{
		if(v != u && !visited[v] && d[v] > d[u]+w[u][v])
		{
			d[v] = d[u]+w[u][v];
			parent[v] = u;//当然,如果题目让输出路径的话直接递归输出,此题没输出,只是加上让大家看一下怎么记录路径
			q.push(make_pair(d[v],v));
		}
	}
	}
}
int main()
{
     int m, a, b, c, st, ed;
     scanf("%d%d", &n, &m);
     for(int i = 1; i <= n; i++)     //邻接矩阵存储前需要初始化
         for(int j = i; j <= n; j++)
             w[i][j] = w[j][i] = INF;
     while(m--)
     {
         scanf("%d%d%d", &a, &b, &c);
         if(w[a][b] > c)
             w[a][b]= w[b][a] = c;
     }
     scanf("%d%d", &st, &ed);
     Dijkstra(st);
     if(d[ed] != INF)
         printf("最短路径权值为:%d\n", d[ed]);
     else
		printf("不存在从顶点%d到顶点%d的最短路径。\n", st, ed);
	 return 0;
}

以上仍然为堆优化dij,但无路径

#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
double dis[101][101];
int x[101],y[101];
int pre[101][101];
int n,i,j,k,m,a,b;
int pf(int x)
{
    return x*x;
}
void print(int x)
{
  if (pre[a][x] == 0) return;    //pre[a][a]=0,说明已经递归到起点a
    print(pre[a][x]);
    cout << "->" << x;
}
int main()
{
    cin >> n;
    for (i = 1; i <= n; i++)
        cin >> x[i] >> y[i];
    memset(dis,0x7f,sizeof(dis));	       //初始化数组
    cin >> m;
    memset(pre,0,sizeof(pre));             //初始化前驱数组
    for (i = 1; i <= m; i++)
    {
        cin >> a >> b;
        dis[a][b] = dis[b][a] = sqrt(pf(x[a]-x[b])+pf(y[a]-y[b]));
    pre[a][b] = a;                         //a与b相连,自然从a到b的最短路径b的前驱是a
        pre[b][a] = b;
    }
    cin >> a >> b;
    for (k = 1; k <= n; k++)               //floyed 最短路
        for (i = 1; i <= n; i++)
            for (j = 1; j <= n; j++)
                if ((i != j) && (i != k) && (j != k))
                    if (dis[i][j] > dis[i][k]+dis[k][j])
                    {
                        dis[i][j] = dis[i][k] + dis[k][j];
                        pre[i][j] = pre[k][j];
 //从i到j的最短路径更新为i→k→j,那么i到j最短路径j的前驱就肯定与k到j最短路径j的前驱相同。
                    }
    cout << a;
  print(b);                                //a是起点,b是终点
    return 0;
}

 弗洛伊德带路径

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
struct data
{
	int q,dat;
    friend bool operator<(data a, data b)   //因要实现最小堆,按升序排列,因而需要重载运算符,重定义优先级,以小为先
	{
		return a.dat > b.dat;
		//priority_queue的排序比较函数和我们的观念相反. priority_queue一般就是用堆做的,默认是用less比较实现的大根堆,
		//比如当先维护堆,从父结点A开始下降整理堆,它会用A的孩子B与A调用less<>对象假设名字叫cmp,会这样传参,
		//if(cmp(A,B)){那么调换A,B结点值} ,less里肯定是 return A<B; 所以我们想要实现小根堆,在传参次序为(A,B)的情况下,
		//只能修改比较函数cmp,如果A<B,返回false,A>B才返回真.
	}
}/*小根堆*/;

priority_queue<data> Q;
struct arr
{
	int ff,tt,ww,next;
}c[5000];
data cc;//建堆用的变量
int a[5000],dis[5000],r[5000];
bool v[5000];
int n,tot = 0,p,C;
void add(int x,int y, int z)
{
	c[++tot].ff = x;
	c[tot].tt = y;
	c[tot].ww = z;
	c[tot].next = r[x];
	r[x] = tot;
}

int dijsktra(int st)
{
	int x,y;
	cc.q = st;
	cc.dat = 0;
	Q.push(cc);
	memset(dis,50,sizeof(dis));//初始化为较大的数8亿多
	memset(v,0,sizeof(v));
	dis[st] = 0;
	while (! Q.empty())
	{
		x = Q.top().q;
		y = Q.top().dat;
		Q.pop(); 
		if (! v[x])
		{
			v[x] = true;
			for (int i = r[x]; i ; i = c[i].next)
			{
				cc.q = c[i].tt;
				if (dis[cc.q]> y+c[i].ww)
				{
				   dis[cc.q] = y+c[i].ww;
				   cc.dat = dis[cc.q];
				   Q.push(cc);
				}
			}
		}
	}
} 

int main()
{
	
	freopen("butter.in","r",stdin);
	freopen("butter.out","w",stdout);
	scanf("%d%d%d",&n,&p,&C);
	int x,y,z;
	for (int i=1; i<=n; i++)
	{
		scanf("%d",&a[i]);
	}
	
	for (int i=1; i<=C; i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	int ans = 0x7fffffff;
	for (int i = 1; i<=p; i++) 
	{
		dijsktra(i);
		int now = 0;
		for (int j = 1; j<=n; j++)
		   now+=dis[a[j]];
		ans = min(ans,now);
		
    }
    printf("%d\n",ans);
    return 0;
	
}

 堆优化dij

#include <bits/stdc++.h>
using namespace std;
bool a[1000][1000];
bool f[1000];
int n,e;
void iint(){
	 memset(a,0,sizeof(a));
	 memset(f,0,sizeof(f));
	 scanf("%d%d",&n,&e);
	 for(int i=1;i<=e;i++){
	 	int x,y;
	 	scanf("%d%d",&x,&y);
	 	a[x][y]=true;
	 	a[y][x]=true;
	 }
}
void bfs(int x){
	 f[x]=true;
	 queue<int> q;
	 q.push(x);
	 printf("%d ",x);
	 while(!q.empty()){
	 	for(int i=1;i<=n;i++){
	 		if(!f[i] && a[q.front()][i]){
	 		    q.push(i);
	 		    f[i]=1;
	 		    printf("%d ",i);
			 }
		 }
		 q.pop();
	 }
}
int main(){
	iint();
	bfs(1);
	return 0;
}

 bfs(广搜)

#include <bits/stdc++.h>
using namespace std;
bool a[110][110];
bool flag[110];
int n,e;
void init();
void dfs(int x);
int main()
{
	init();
	dfs(1);
	return 0;
}
void init(){
	scanf("%d%d",&n,&e);
	memset(flag,0,sizeof(flag));
	memset(a,0,sizeof(a));
	int x,y;
	for(int i=1;i<=e;++i){
		cin>>x>>y;
		a[x][y]=1;
		a[y][x]=1;
	}
}
void dfs(int x){
	printf("%d ",x);
	flag[x]=1;
	for(int i=1;i<=n;++i) 
	  if(!flag[i]&&a[x][i]==1)
	       dfs(i);
}

 dfs(深搜)

posted @ 2021-10-14 09:45  kiritokazuto  阅读(156)  评论(0)    收藏  举报