zoukankan      html  css  js  c++  java
  • [Luogu P4779] 单源最短路径(标准版)

    以此题为例,总结所有的最短路算法。

    Floyd

    用w[i][j]记录i到j的最短路,实质上是DP。

    记得初始化:存在i->j则w[i][j]=e[i][j],w[i][i]=0,其余w[i][j]=inf。

    复杂度O(n^3)。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int inf=0x7f7f7f7f;
    long long w[1010][1010];
    int main()
    {
    	int n,m,i,j,k,x,y,z;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=n;j++)
    		w[i][j]=inf;
    	}
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		w[x][y]=z;
    	}
    	for(i=1;i<=n;i++)w[i][i]=0;
    	for(k=1;k<=n;k++)
    	{
    		for(i=1;i<=n;i++)
    		{
    			for(j=1;j<=n;j++)
    			{
    				if(w[i][j]>w[i][k]+w[k][j])
    				w[i][j]=w[i][k]+w[k][j];
    			}
    		}
    	}
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=n;j++)
    		printf("%d ",w[i][j]);
    		printf("
    ");
    	}
    	return 0;
    }
    

    SPFA

    类似于bfs,用一个队列来维护被松弛过的点,每次松弛队首元素向外连的点的最短路,并将这些点push到队列里。记录一个vis[i]表示i是否在队列里可以减少入队次数。

    复杂度最坏O(n*m)。可以处理负权边,判环,但是如果只求正权图最短路使用Dijkstra更好。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    int read()
    {
    	int x=0;bool f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    const int inf=0x7f7f7f7f;
    struct edge
    {
    	int v,last,w;
    }e[2000010];
    int in[1000010],cnt=0;
    void addedge(int x,int y,int z)
    {
    	e[++cnt].v=y;
    	e[cnt].last=in[x];
    	e[cnt].w=z;
    	in[x]=cnt;
    }
    queue<int>q;
    bool vis[1000010];
    int dis[1000010];
    void spfa(int st)
    {
    	int i,cur,t;
    	memset(dis,127,sizeof(dis));
    	dis[st]=0;
    	q.push(st);
    	vis[st]=1;
    	while(!q.empty())
    	{
    		cur=q.front();q.pop();
    		vis[cur]=0;
    		for(i=in[cur];i;i=e[i].last)
    		{
    			t=e[i].v;
    			if(dis[t]>dis[cur]+e[i].w)
    			{
    				dis[t]=dis[cur]+e[i].w;
    				if(!vis[t])
    				{
    					vis[t]=1;
    					q.push(t);
    				}
    			}
    		}
    	}
    	return;
    }
    int main()
    {
    	int n,m,i,j,k,x,y,z,S;
    	n=read(),m=read(),S=read();
    	for(i=1;i<=m;i++)
    	{
    		x=read(),y=read(),z=read();
    		addedge(x,y,z);
    	}
    	spfa(S);
    	for(i=1;i<=n;i++)
    	printf("%d ",dis[i]);
    	return 0;
    }
    

    Dijkstra

    每次更新的是还没访问到的最短路距离最小的点向外连的点。实质是贪心,用堆可以加快速度。复杂度O(nlogn)。不能处理负权边。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    int read()
    {
    	int x=0;bool f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    const int inf=0x7f7f7f7f;
    struct edge
    {
    	int v,last,w;
    }e[2000010];
    int in[1000010],cnt=0;
    void addedge(int x,int y,int z)
    {
    	e[++cnt].v=y;
    	e[cnt].last=in[x];
    	e[cnt].w=z;
    	in[x]=cnt;
    }
    struct node
    {
    	int dist,pos;
    	friend bool operator < (node x,node y)
    	{
    		return x.dist>y.dist;
    	}
    };
    priority_queue<node>q;
    int dis[1000010];
    bool vis[1000010];
    void dijkstra(int st)
    {
    	int i,cur,t;
    	memset(dis,127,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	while(!q.empty())q.pop();
    	dis[st]=0;
    	q.push((node){0,st});
    	while(!q.empty())
    	{
    		cur=q.top().pos;q.pop();
    		if(vis[cur])continue;
    		vis[cur]=1;
    		for(i=in[cur];i;i=e[i].last)
    		{
    			t=e[i].v;
    			if(dis[t]>dis[cur]+e[i].w)
    			{
    				dis[t]=dis[cur]+e[i].w;
    				if(!vis[t])q.push((node){dis[t],t});
    			}
    		}
    	}
    	return;
    }
    int main()
    {
    	int n,m,i,j,k,x,y,z,S;
    	n=read(),m=read(),S=read();
    	for(i=1;i<=m;i++)
    	{
    		x=read(),y=read(),z=read();
    		addedge(x,y,z);
    	}
    	dijkstra(S);
    	for(i=1;i<=n;i++)
    	printf("%d ",dis[i]);
    	return 0;
    }
    
  • 相关阅读:
    ADODB.Stream
    今天发现一个好玩的翻译接口
    有趣的对角线公式
    jboss 虚拟路径
    省市区拆分字符串
    jboss-eap-6.2修改端口号
    把excel、txt当数据库来查询
    TS流PAT/PMT详解
    iOS/iPhone 程序文件目录结构以及启动流程
    onvif规范的实现:onvif开发常用调试方法 和常见的segmentation fault错误
  • 原文地址:https://www.cnblogs.com/Rain142857/p/11791400.html
Copyright © 2011-2022 走看看