图论基础——-最短路径

最短路径的dij算法:贪心的找出距离最短的点,由此来松弛其他点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int cnt=0;
int head[maxn],d[maxn],v[maxn];
struct node
{
    int y,t,p;
}s[maxn<<1];
void add(int n,int m,int k)
{
    s[++cnt]=node{m,k,head[n]};
    head[n]=cnt;
}
void dij(int x)
{
    memset(v,0,sizeof(v));
    memset(d,inf,sizeof(d));
    d[x]=0;
    for(int i=1;i<=n;i++){
        int minn=-1;
        for(int j=1;j<=n;j++){
            if(!v[j]){
                if(minn==-1||d[j]<d[minn]){
                    minn=j;
                }
            }
        }
        if(d[minn]==inf)break;
        v[minn]=1;
        for(int j=head[minn];~j;j=s[j].p){
            int a=s[j].y;
            int b=s[j].t;
            if(!v[a]){
                if(d[a]>b+d[minn]){
                    d[a]=b+d[minn];
                }
            }
        }
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m)){
        if(n==m&&m==0)break;
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        dij(1);
        printf("%d\n",d[n]);
    }
    return 0;
}



dij算法用优先队列优化的邻接表方式:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int>p;
int n,m;
int cnt=0;
int head[maxn],d[maxn];
struct node
{
    int y,t,p;
    friend operator <(node a,node b){
        return a.p<b.p;
    }
}s[maxn<<1];
void add(int n,int m,int k)
{
    s[++cnt]=node{m,k,head[n]};
    head[n]=cnt;
}
void dij(int x)
{
    memset(d,inf,sizeof(d));
    d[x]=0;
    p o={0,x};
    priority_queue<p>q;
    q.push(o);
    while(!q.empty()){
        p w=q.top();
        q.pop();
        int r=w.second;
        if(d[r]<w.first)continue;
        for(int i=head[r];~i;i=s[i].p){
            int a=s[i].y;
            int b=s[i].t;
            if(d[a]>b+d[r]){
                d[a]=b+d[r];
                q.push(p(d[a],a));
            }
        }
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m)){
        if(n==m&&m==0)break;
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        dij(1);
        printf("%d\n",d[n]);
    }
    return 0;
}

SPFA算法:与BFS思想类似,但是对于一个元素允许出入队列多次:
SPFA还可以运用堆栈的思想来解决,其相当与DFS,而且更快

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int cnt=0;
int head[maxn],d[maxn],v[maxn];
struct node
{
    int y,t,p;
}s[maxn<<1];
void add(int n,int m,int k)
{
    s[++cnt]=node{m,k,head[n]};
    head[n]=cnt;
}
void spfa(int n)
{
    queue<int>q;
    memset(v,0,sizeof(v));
    memset(d,inf,sizeof(d));
    d[n]=0;
    q.push(n);
    v[n]=0;
    while(!q.empty()){
        int w=q.front();
        q.pop();
        v[w]=0;
        for(int i=head[w];~i;i=s[i].p){
            int a=s[i].y;
            int b=s[i].t;
            if(d[a]>b+d[w]){
                d[a]=b+d[w];
                if(!v[a]){
                    q.push(a);
                    v[a]=1;
                }
            }
        }
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m)){
        if(n==m&&m==0)break;
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        spfa(1);
        printf("%d\n",d[n]);
    }
    return 0;
}

弗洛伊德算法:求出所有点的最短路径,用了动态规划的思想,其中dp[k][i][j]是指在只使用前0~k个点的情况下的从I点到J点的最短路径。
题目:六度分离

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 205;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int dp[maxn][maxn];
int main()
{
    while(~scanf("%d %d",&n,&m)){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j)
                    dp[i][j]=0;
                else
                    dp[i][j]=inf;
            }
        }
        int a,b;
        for(int i=0;i<m;i++){
            scanf("%d %d",&a,&b);
            dp[a][b]=dp[b][a]=1;
        }
        for(int k=0;k<n;k++)
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++){
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
        }
        int flag=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(dp[i][j]>7){
                    printf("No\n");
                    flag=1;
                    break;
                }
            }
            if(flag==1)
                break;
        }
        if(!flag)
            printf("Yes\n");
    }
    return 0;
}

PS:我太菜了只能做这些模板题。

发布了35 篇原创文章 · 获赞 25 · 访问量 838

猜你喜欢

转载自blog.csdn.net/qq_43816599/article/details/95920094