最短路算法

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1010;

//重点在建图!
/*步骤:1.先初始化距离dist[1] = 0,dist[i] = INF;2.for循环,i从0到n循环
* (已经确定最短距离的点放到s里面),找到不在s中的距离最近的点t,把t加到s里面,
* 用t更新其他点的距离
*/

int n, m;
int g[N][N], dis[N];
bool st[N];

int Dijkstra()
{
	memset(dis, INF, sizeof(dis));
	dis[1] = 0;

	for (int i = 0; i < n; i++)
	{
		int t = -1;
		for (int j = 1; j <= n; j++)
		{
			if (!st[j] && (t == -1 || dis[t] > dis[j])) t = j;
		}
		st[t] = true;
		for (int j = 1; j <= n; j++)
		{
			dis[j] = min(dis[j], dis[t] + g[t][j]);
		}
	}
	if (dis[n] == INF) return -1;
	else return dis[n];
}

int main()
{
	cin >> n >> m;

	memset(g, INF, sizeof(g));

	for (int i = 1; i <= m; i++)
	{
		int start, end, len;
		cin >> start >> end >> len;
		g[start][end] = g[end][start] = len;
	}
	int t = Dijkstra();
	cout << t << endl;
	return 0;
}

2.堆优化版的Djikstra算法:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef pair<int,int>PII;
const int N=1e6+10;
const int INF=0x3f3f3f3f;

int n,m;
int h[N],e[N],w[N],ne[N],idx=0;
int dist[N];
bool st[N];

void add(int a,int b,int c)
{
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

int dijkstra()
{
    memset(dist,INF,sizeof(dist));
    priority_queue<PII,vector<PII>,greater<PII>>heap;
    dist[1]=0;
    heap.push({0,1});
    
    while(heap.size())
    {
        auto t=heap.top();
        heap.pop();
        
        int p=t.second;
        if(st[p]) continue;
        st[p]=1;
        for(int i=h[p];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[p]+w[i]) 
            {
                dist[j]=dist[p]+w[i];
                heap.push({dist[j],j});
            }
        }
    }
    
    if(dist[n]==INF) return -1;
    return dist[n];
}

int main()
{
    memset(h,-1,sizeof(h));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    
    printf("%d\n",dijkstra());
    return 0;
}

3.Bellman_ford算法

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510,M=10010;

int n,m,k;
struct Edg{
    int a;
    int b;
    int w;
}Edgs[M];
int dist[N],backup[N];

int bellman_ford()
{
    memset(dist,0x3f,sizeof(dist));
    dist[1]=0;
    
    for(int i=0;i<k;i++)
    {
        memcpy(backup,dist,sizeof(dist));//backup用来做备份
        for(int j=1;j<=m;j++)
        {
            int a=Edgs[j].a,b=Edgs[j].b,w=Edgs[j].w;
            dist[b]=min(dist[b],backup[a]+w);
        }
    }
    
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        Edgs[i]={a,b,c};
    }
    bellman_ford();
    if(dist[n]>0x3f3f3f3f/2) puts("impossible");//因为存在负权边
    else printf("%d\n",dist[n]);
    return 0;
}

4.SPFA算法:

(1).求最短路:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;


//spfa优化bellman_ford算法,更新过谁了,再拿谁放在队列里,然后用它更新其他的点
int n,m;
int h[N],e[N],w[N],ne[N],idx=0;
int dist[N];
bool st[N];//看这个点他是否在队列里面

void add(int a,int b,int c)
{
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

int spfa()
{
    memset(dist,0x3f,sizeof(dist));
    dist[1]=0;
    queue<int>q;
    
    q.push(1);
    st[1]=true;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[t]+w[i])
            {
                dist[j]=dist[t]+w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    //if(dist[n]==0x3f3f3f3f) return -1;
    return dist[n];
}

int main()
{
    memset(h,-1,sizeof(h));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    
    int t=spfa();
    if(t==0x3f3f3f3f) puts("impossible");
    else printf("%d\n",t);
    return 0;
}

(2).判断负环

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;


//这个图了只有n个点,最短路没有环的话就绝对不会超过n-1条边
//count[x]大于等于n-1了,那么一定存在负环

int n,m;
int h[N],e[N],w[N],ne[N],idx=0;
int dist[N],cnt[N];
bool st[N];//看这个点他是否在队列里面

void add(int a,int b,int c)
{
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

bool spfa()
{
    queue<int>q;
 
    for(int i=1;i<=n;i++)
    {
        q.push(i);
        st[i]=true;
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[t]+w[i])
            {
                dist[j]=dist[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    
}

int main()
{
    memset(h,-1,sizeof(h));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    
    if(spfa()==true) puts("Yes");
    else puts("No");
    return 0;
}

5.多源最短路Floyd算法:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=1e9;
const int N=210;


//三重循环,存图是矩阵存
int n,m,t;
int d[N][N];


int main()
{
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j) d[i][j]=0;
            else d[i][j]=INF;
        }
    }
    
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        d[x][y]=min(d[x][y],z);
    }
    
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(d[i][j]>d[i][k]+d[k][j])
                {
                    d[i][j]=d[i][k]+d[k][j];
                }
            }
        }
    }
    while(t--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(d[a][b]>INF/2) puts("impossible");
        else printf("%d\n",d[a][b]);
    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值