单源最短路的建图方式acm


#写在前面

一些例题bale

##热浪

https://www.acwing.com/problem/content/1131/

----c++版

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
//裸单源最短路 dijketra On^2, 堆dijkstra Omlogn, spfa Om

const int N=2510, M=6200*2+10;

int n,m, S, T;
int h[N], e[M], w[M], ne[M], idx;
int dist[N], q[N];
bool st[N];

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

void spfa(){
    memset(dist, 0x3f, sizeof dist);
    dist[S]=0;
    int hh=0, tt=1;
    q[0]=S, st[S]=true;
    
    while(hh!=tt){
        int t=q[hh++];
        if(hh==N)hh=0;
        st[t]=false;
        
        for(int i=h[t]; ~i; i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[t]+w[i]){
                dist[j]=dist[t]+w[i];
                if(!st[j]){
                    q[tt++]=j;
                    if(tt==N)tt=0;
                    st[j]=true;
                }
            }
        }
    }
}

int main(){
    cin>>n>>m>>S>>T;
    memset(h, -1, sizeof h);
    
    for(int i=0; i<m; i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c); add(b, a, c);
    }
    
    spfa();
    
    cout<<dist[T]<<endl;
    return 0;
}

##信使

https://www.acwing.com/problem/content/1130/

----c++版

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
//对除了起点外每个点跑一边最短路,输出最长的距离
//可以用floyd
const int N=110, inf=0x3f3f3f3f;

int n,m;
int d[N][N];

int main(){
    cin>>n>>m;
    memset(d, 0x3f, sizeof d);
    for(int i=0; i<m; i++){
        int a,b,c;
        cin>>a>>b>>c;
        d[a][b]=d[b][a]=min(d[a][b], c);
    }
    
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                d[i][j]=min(d[i][j], d[i][k]+d[k][j]);
                
    int res=0;
    for(int i=1; i<=n; i++)
        if(d[1][i]==inf){
            res=-1;
            break;
        }
        else res=max(res, d[1][i]);
    cout<<res<<endl;
    
    return 0;
}

##香甜的黄油

https://www.acwing.com/problem/content/1129/

----c++版

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
//多源汇最短路问题
//floyd超时
//dijkstra超时
//堆dijkstra nmlogn 1450*800log800
//spfa nm 有风险 nnm

const int N=810, M=3000, inf=0x3f3f3f3f;
int n,m,p;
int id[N];
int h[N], e[M], w[M], ne[M], idx;
int dist[N], q[N];
bool st[N];

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

int spfa(int start){
    memset(dist, 0x3f, sizeof dist);
    dist[start]=0;
    
    int hh=0, tt=1;
    q[0]=start, st[start]=true;
    while(hh!=tt){
        int t=q[hh++];
        if(hh==N)hh=0;
        st[t]=false;
        
        for(int i=h[t]; ~i; i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[t]+w[i]){
                dist[j]=dist[t]+w[i];
                if(!st[j]){
                    q[tt++]=j;
                    if(tt==N)tt=0;
                    st[j]=true;
                }
            }
        }
    }
    int res=0; 
    for(int i=0; i<n; i++){
        int j=id[i];
        if(dist[j]==inf)return inf;
        res+=dist[j];
    }
    return res;
}

int main(){
    cin>>n>>p>>m;
    for(int i=0; i<n; i++)cin>>id[i];
    memset(h, -1, sizeof h);
    
    for(int i=0; i<m; i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a, b, c); add(b, a, c);
    }
    
    int res=inf;
    for(int i=1; i<=p; i++)res=min(res, spfa(i));
    
    cout<<res<<endl;
    return 0;
}

##最小花费

https://www.acwing.com/problem/content/1128/

在这里插入图片描述
对于乘法的题目

乘数都是大于1的-----------dijkstra就好
        大于0的-----------spfa

----c++版

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;

//对等式取log,乘-1,问题变成单源最短路
//直接写乘法也可以

const int N=2010;
int n,m,S,T;
double g[N][N];
double dist[N];
bool st[N];

void dijkstra(){
    dist[S]=1;
    for(int i=1; i<=n; i++){
        int t=-1;
        for(int j=1; j<=n; j++)
            if(!st[j]&&(t==-1||dist[t]<dist[j]))
                t=j;
        st[t]=true;
        
        for(int j=1; j<=n; j++)
            dist[j]=max(dist[j], dist[t]*g[t][j]);
    }
}

int main(){
    scanf("%d%d", &n,&m);
    
    while(m--){
        int a,b,c;
        scanf("%d%d%d", &a,&b,&c);
        double z=(100.0-c)/100;
        g[a][b]=g[b][a]=max(g[a][b], z);
    }
    cin>>S>>T;
    
    dijkstra();
    
    printf("%.8lf\n", 100/dist[T]);
    return 0;
}

##最优乘车

https://www.acwing.com/problem/content/922/
在这里插入图片描述

其中每条边的权重是1

----c++版

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#include<sstream>

const int N=510;
int n,m;
bool g[N][N];
int dist[N];
int stop[N];
int q[N];
bool st[N];

void bfs(){
    int hh=0, tt=0; 
    memset(dist, 0x3f, sizeof dist);
    q[0]=1;
    dist[1]=0;
    
    while(hh<=tt){
        int t=q[hh++];
        for(int i=1; i<=n; i++)
            if(g[t][i]&&dist[i]>dist[t]+1){
                dist[i]=dist[t]+1;
                q[++tt]=i;
            }
    }
}

int main(){
    cin>>m>>n;
    
    string line;
    getline(cin, line);//读掉第一行
    while(m--){
        getline(cin, line);
        stringstream ssin(line);
        int cnt=0, p;
        while(ssin>>p)stop[cnt++]=p;
        for(int j=0; j<cnt; j++)
            for(int k=j+1; k<cnt; k++)
                g[stop[j]][stop[k]]=true;//线路是单程的
    }
    bfs();
    if(dist[n]==0x3f3f3f3f)puts("NO");
    else cout<<max(dist[n]-1, 0)<<endl;
    return 0;
}

##昂贵的聘礼

https://www.acwing.com/problem/content/905/
在这里插入图片描述

----c++版

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110, inf=0x3f3f3f3f;
int n,m;
int w[N][N], level[N];
int dist[N];
bool st[N];

int dijkstra(int down, int up){
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);
    
    dist[0]=0;
    for(int i=1; i<=n+1; i++){
        int t=-1;
        for(int j=0; j<=n; j++)
            if(!st[j]&&(t==-1||dist[t]>dist[j]))
                t=j;
        
        st[t]=true;
        for(int j=1; j<=n; j++)
            if(level[j]>=down&&level[j]<=up)
                dist[j]=min(dist[j], dist[t]+w[t][j]);
    }
    return dist[1];
}


int main(){
    cin>>m>>n;
    
    memset(w, 0x3f, sizeof w);
    for(int i=1; i<=n; i++)w[i][i]=0;//self 2 self
    
    for(int i=1; i<=n; i++){
        int price, cnt;
        cin>>price>>level[i]>>cnt;
        w[0][i]=min(price, w[0][i]);//虚拟原点
        
        while(cnt--){
            int id, cost;
            cin>>id>>cost;
            w[id][i]=min(w[id][i], cost);
        }
        
    }
    
    int res=inf;
    for(int i=level[1]-m; i<=level[1]; i++) res=min(res, dijkstra(i, i+m));//dij传入等级区间的范围
    
    cout<<res<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值