图论第一发————最短路

图    n个点 ,m条边(点,边都可以有权值)

存储  邻接矩阵  n*n   (基本被淘汰啦)

          临接表 

核心代码没几行  临接表 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int num=0;
int head[10005]={0},nxt[10005]={0},to[10005]={0},v[10005]={0};
int n,m;

void add(int x,int y,int z);
{
	num++;
	nxt[num]=head[x];    //head(x点连的第一条边)    
	head[x]=num;         //nxt (一条边后的另一条边) 
	to[num]=y;
	v[num]=z;
}

int main()
{   
    scanf("%d%d",&n,&m);
    int x,y,z;
    for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		//add(y,x,z);  //无向图 
	}  
    return 0;
}

任意两点间的最短路

Floyd算法

  1. 本质  dp      D[i,j]=min ( D[i,j] , D[i,k]+D[k,j] )  D[i,j]  最后出现最短路
  2. 状态  k  最外层
  3. 时间复杂度 (n^{3}{\color{Blue} })  空间复杂度(n^{2}
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int n,m;
int a[1005][1005]={0};
int main()
{   
    for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++) 
	a[i][j]=2147483647;
	 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) 
    for(int j=1;j<=n;j++)
    scanf("%d",&a[i][j]);
    
    for(int k=1;k<=n;k++)
  	for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    a[i][j]=min(a[i][k]+a[k][j],a[i][j]);
    
    for(int i=1;i<=n;i++) 
    for(int j=1;j<=n;j++)
    printf("%d ",a[i][j]);
    
    return 0;
}

单元最短路

Dijkstra 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue> 
using namespace std;
int num=0;
int head[500005]={0},nxt[500005]={0},to[500005]={0},v[500005]={0}; 
int n,m,k;
int b[10005]={0};//是否出队   
priority_queue< pair<int,int> > q;  //一维 d的相反数  二维 编号 
int d[10005]={0};  //最短路 
void add(int x,int y,int z)
{
	nxt[++num]=head[x];    //head(x点连的第一条边)    
	head[x]=num;         //nxt (一条边后的另一条边) 
	to[num]=y;
	v[num]=z;
}

void dj() //边非负 
{
	for(int i=1;i<=n;i++)  d[i]=2147483647;
	memset(b,0,sizeof(b));
	d[k]=0; 
	q.push(make_pair(0,k)); //出现疑似最短路入队 
	while(!q.empty())//出队最短路已确定 
	{
		int x=q.top().second; q.pop();    //找最小 
		if(b[x])  continue;   b[x]=1;     //标记 
		for(int i=head[x];i;i=nxt[i])     //用最小更新 
		{
			int y=to[i]; 
			if(d[y]>d[x]+v[i]) 
			{
				d[y]=d[x]+v[i];
				q.push(make_pair(-d[y],y));
	
			}  
			
		}
	}
}

int main()
{   
    scanf("%d%d%d",&n,&m,&k);
    int x,y,z;
    for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		//add(y,x,z);  //无向图 
	}  
	
    dj();
	
	for(int i=1;i<=n;i++)  
	printf("%d ",d[i]);
	
    return 0;
}

spfa  

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,s;
int head[500005]={0},nxt[500005]={0},to[500005]={0},v[500005]={0};
int num=0;
int l=1,r=0;
int b[100005]={0},q[100005]={0};
int d[100005]={0};
void add(int x,int y,int z)
{
	nxt[++num]=head[x];
	head[x]=num;
	to[num]=y;
	v[num]=z;
}

void spfa()
{
     memset(b,0,sizeof(b));
     for(int i=1;i<=n;i++)  d[i]=2147483647;
     d[s]=0;  
	 b[s]=1;  q[++r]=s; 
	 while(l<=r)
	 {
	 	int x=q[l++]; b[x]=0;
	 	for(int i=head[x];i;i=nxt[i])
	 	{
	 		int y=to[i];
	 		if(d[y]>d[x]+v[i])  
	 		{
	 			d[y]=d[x]+v[i];
	 			if(b[y]==0)  b[y]=1,q[++r]=y; 
	 		}
	 	} 
	 }
	   
     return;
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
	

	for(int i=1;i<=m;i++)
	{
		int x,y,v;
		scanf("%d%d%d",&x,&y,&v);
	    add(x,y,v);
	}
    spfa();
   
    for(int i=1;i<=n;i++) printf("%d ",d[i]);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42146446/article/details/81140834