SPFA 上手题 数 枚:

1, HDU 1548 A strange lift :http://acm.hdu.edu.cn/showproblem.php?pid=1548

这道题可以灰常巧妙的转换为一道最短路题目,对第i层,按钮数字为button[i],则如果满足相加<=N,则把i到i+button[i]的路径长度设为1(巧妙将按钮次数转换为路径长度),同理,相减如果满足>=1,则把i到i-button[i]的路径长度设为1.则最后输出终点的最短路的长度即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int INF=0x3f3f3f3f;

int n,a,b;
int map[210][210],vis[210],dis[210];

int SPFA(){
    for(int i=1;i<=n;i++){
        dis[i]=INF;
        vis[i]=0;
    }
    queue<int> q;
    while(!q.empty())
        q.pop();
    dis[a]=0;
    vis[a]=1;
    q.push(a);
    while(!q.empty()){
        int cur=q.front();
        q.pop();
        vis[cur]=0;
        for(int i=1;i<=n;i++)
            if(dis[i]>dis[cur]+map[cur][i]){
                dis[i]=dis[cur]+map[cur][i];
                if(!vis[i]){
                    vis[i]=1;
                    q.push(i);
                }
            }
    }
    return dis[b];
}

int main(){

    //freopen("input.txt","r",stdin);

    while(~scanf("%d",&n) && n){
        scanf("%d%d",&a,&b);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                map[i][j]=INF;
        int x;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            if(i-x>=1)
                map[i][i-x]=1;
            if(i+x<=n)
                map[i][i+x]=1;
        }
        int ans=SPFA();
        if(ans==INF)
            ans=-1;
        printf("%d
",ans);
    }
    return 0;
}
View Code

另附BFS解法:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

int n,a,b;
int k[210],vis[210];

struct node{
    int x,step;
};

int BFS(){
    queue<node> q;
    while(!q.empty())
        q.pop();
    node cur,next;
    cur.x=a,    cur.step=0;
    vis[cur.x]=1;
    q.push(cur);
    while(!q.empty()){
        cur=q.front();
        q.pop();
        if(cur.x==b)
            return cur.step;
        next.x=cur.x-k[cur.x];
        next.step=cur.step+1;
        if(next.x>=1 && next.x<=n && !vis[next.x]){
            vis[next.x]=1;
            q.push(next);
        }
        next.x=cur.x+k[cur.x];
        if(next.x>=1 && next.x<=n && !vis[next.x]){
            vis[next.x]=1;
            q.push(next);
        }
    }
    return -1;
}

int main(){

    //freopen("input.txt","r",stdin);

    while(~scanf("%d",&n) && n){
        scanf("%d%d",&a,&b);
        for(int i=1;i<=n;i++)
            scanf("%d",&k[i]);
        memset(vis,0,sizeof(vis));
        int ans=BFS();
        printf("%d
",ans);
    }
    return 0;
}
View Code

2,  HDU 3790 最短路径问题 : http://acm.hdu.edu.cn/showproblem.php?pid=3790

二维距离(路程,价格),优先判断路程…

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int VM=1010;
const int EM=100010;
const int INF=0x3f3f3f3f;

struct Edge{
    int to,nxt;
    int cap,cost;
}edge[EM<<1];

int n,m,cnt,head[VM];
int src,des,dis[VM],pay[VM],vis[VM];

void addedge(int cu,int cv,int cw,int cc){
    edge[cnt].to=cv;    edge[cnt].cap=cw;   edge[cnt].cost=cc;
    edge[cnt].nxt=head[cu];     head[cu]=cnt++;
}

void SPFA(){
    for(int i=1;i<=n;i++){
        dis[i]=INF;
        pay[i]=INF;
        vis[i]=0;
    }
    queue<int> q;
    while(!q.empty())
        q.pop();
    dis[src]=0;
    pay[src]=0;
    vis[src]=1;
    q.push(src);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].cap || (dis[v]==dis[u]+edge[i].cap && pay[v]>pay[u]+edge[i].cost)){    //二维距离(路程,价格),优先判断路程…
                dis[v]=dis[u]+edge[i].cap;
                pay[v]=pay[u]+edge[i].cost;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

int main(){

    //freopen("input.txt","r",stdin);

    while(~scanf("%d%d",&n,&m)){
        if(n==0 && m==0)
            break;
        cnt=0;
        memset(head,-1,sizeof(head));
        int u,v,d,p;
        while(m--){
            scanf("%d%d%d%d",&u,&v,&d,&p);
            addedge(u,v,d,p);   //因为是无向边,所以建双向图
            addedge(v,u,d,p);
        }
        scanf("%d%d",&src,&des);
        SPFA();
        printf("%d %d
",dis[des],pay[des]);
    }
    return 0;
}
View Code

3, HDU  2066  一个人的旅行 : http://acm.hdu.edu.cn/showproblem.php?pid=2066

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int INF=0x3f3f3f3f;

struct Edge{
    int to,nxt;
    int cap;
}edge[100010];

int T,S,D;
int cnt,head[1100];
int src,des,dis[1100],vis[1100];

void addedge(int cu,int cv,int cw){
    edge[cnt].to=cv;    edge[cnt].cap=cw;   edge[cnt].nxt=head[cu];
    head[cu]=cnt++;
}

int SPFA(){
    queue<int> q;
    while(!q.empty())
        q.pop();
    for(int i=0;i<=1001;i++){
        dis[i]=INF;
        vis[i]=0;
    }
    dis[src]=0;
    vis[src]=1;
    q.push(src);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].cap){
                dis[v]=dis[u]+edge[i].cap;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return dis[des];
}

int main(){

    //freopen("input.txt","r",stdin);

    while(~scanf("%d%d%d",&T,&S,&D)){
        cnt=0;
        memset(head,-1,sizeof(head));
        int u,v,w;
        while(T--){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        src=0,  des=1001;
        while(S--){
            scanf("%d",&v);
            addedge(src,v,0);
        }
        while(D--){
            scanf("%d",&u);
            addedge(u,des,0);
        }
        int ans=SPFA();
        printf("%d
",ans);
    }
    return 0;
}
View Code

4, HDU  2112  HDU Today : http://acm.hdu.edu.cn/showproblem.php?pid=2112

trick:起点和终点有可能是同一点,坑爹呐。。。。。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>

using namespace std;

const int N=100010;
const int INF=0x3f3f3f3f;

struct Edge{
    int to,nxt;
    int cap;
}edge[N<<1];

int all,cnt,head[N];
int src,des,dis[N],vis[N];

void addedge(int cu,int cv,int cw){
    edge[cnt].to=cv;    edge[cnt].cap=cw;   edge[cnt].nxt=head[cu];
    head[cu]=cnt++;
}

int SPFA(){
    queue<int> q;
    while(!q.empty())
        q.pop();
    for(int i=0;i<=all;i++){
        dis[i]=INF;
        vis[i]=0;
    }
    dis[src]=0;
    vis[src]=1;
    q.push(src);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].cap){
                dis[v]=dis[u]+edge[i].cap;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return dis[des];
}

int main(){

    //freopen("input.txt","r",stdin);

    int n;
    char str1[40],str2[40];
    char s[40],t[40];
    map<string,int> mp;
    while(~scanf("%d",&n) && n!=-1){
        cnt=0;
        memset(head,-1,sizeof(head));
        all=1;
        mp.clear();
        scanf("%s%s",s,t);
        mp[s]=all++;    //起点和终点有可能是同一点
        src=mp[s];
        if(mp[t]==0)
            mp[t]=all++;
        des=mp[t];
        int w;
        while(n--){
            scanf("%s%s%d",str1,str2,&w);
            if(mp[str1]==0)
                mp[str1]=all++;
            if(mp[str2]==0)
                mp[str2]=all++;
            addedge(mp[str1],mp[str2],w);
            addedge(mp[str2],mp[str1],w);
        }
        int ans=SPFA();
        if(ans==INF)
            ans=-1;
        printf("%d
",ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jackge/p/3164300.html