zoukankan      html  css  js  c++  java
  • [SPFA (Bellman Ford)] POJ 1860 Currency Exchange | POJ 3259 Wormholes | LightOJ 1074 Extended Traffic

    POJ 1860 Currency Exchange | POJ 3259 Wormholes | LightOJ 1074 Extended Traffic

    SPFA (Bellman Ford)

    POJ 1860 Currency Exchange

    #include"stdio.h"
    #include"string.h"
    #include"math.h"
    #include<vector>
    #include<queue>
    #include<functional>
    #include<algorithm>
    using namespace std;
    typedef pair<double,double> Pair;
    typedef pair<double,int> PairDI;
    const int MAX_NM=103;
    const int MAX_V=1003;
    int N;// n currency, 1-indexed
    int M;// n ExPoints
    int S;
    double V;
    
    Pair G[MAX_NM][MAX_NM];
    double dis[MAX_NM];
    bool vis[MAX_NM];
    int cnt[MAX_NM];
    bool SPFA(int S){
        dis[S]=V;
        priority_queue<PairDI> Q;// max heap
        Q.push(PairDI(dis[S],S));
        vis[S]=true;
        ++cnt[S];
        while(!Q.empty()){
            PairDI p = Q.top();
            Q.pop();
            int cur = p.second;
            vis[cur]=false;
            for(int i=1;i<=N;i++){
                if(G[cur][i].first==0.0) continue;// no path
                double r = G[cur][i].first;
                double c = G[cur][i].second;
                if((dis[cur]-c)*r > dis[i]){
                    // printf("%d %d
    ", cur,i);
                    dis[i] = (dis[cur]-c)*r;
                    if(!vis[cur]){
                        Q.push(Pair(dis[i],i));
                        vis[i]=true;
                        if(++cnt[i] > N-1) return true;
                    }
                }
            }
        }
        return false;// 不存在“负权环”
    }
    
    int main(){
        fill(G[0],G[0]+MAX_NM*MAX_NM,Pair(0,0));
        fill(dis,dis+MAX_NM,0);
        fill(vis,vis+MAX_NM,false);
        fill(cnt,cnt+MAX_NM,0);
        scanf("%d%d%d%lf",&N,&M,&S,&V);
        for(int m=0;m<M;m++){
            int A,B;
            double R_AB,C_AB,R_BA,C_BA;
            scanf("%d %d %lf %lf%lf %lf",&A,&B,&R_AB,&C_AB,&R_BA,&C_BA);
            G[A][B] = Pair(R_AB,C_AB);
            G[B][A] = Pair(R_BA,C_BA);
        }
        if(SPFA(S)) printf("YES
    ");
        else printf("NO
    ");
        return 0;
    }
    
    

    POJ 3259 Wormholes

    • 判断是否存在负环(从任源点出发),每个节点作源进行SPFA显然会TLE。
    • 只进行一次单源SPFA:
      • 添加辅助顶点C,有向边S->C,有向边C->v (其中v∈V - {S} )。即可只进行一次单源SPFA;
      • 同时防止因添加顶点C引入了负环,因此:
      • 这些有向边的权重ω要足够大,满足2ω>MAX_NW(负权边的绝对值的最大值)。
    /* #include 省略 */
    typedef pair<int,int> Pair;
    const int MAX_N = 503;
    int N;// fields, 1~500
    int M;// paths
    int W;// wormholes
    int G[MAX_N][MAX_N];
    int dis[MAX_N];
    bool vis[MAX_N];
    int cnt[MAX_N];
    bool SPFA(int s){
        dis[s]=0;
        priority_queue<Pair,vector<Pair>,greater<Pair>> Q;// min heap
        Q.push(Pair(dis[s],s));
        vis[s]=true;
        cnt[s]++;
        while(!Q.empty()){
            Pair p = Q.top();
            Q.pop();
            int cur = p.second;
            vis[cur]=false;
            for(int i=1;i<=N+1;i++){
                if(G[cur][i]>10000) continue;
                if(dis[cur]+G[cur][i] < dis[i]){
                    // printf("%d %d
    ", cur,i);
                    dis[i] = dis[cur]+G[cur][i];
                    if(!vis[cur]){
                        Q.push(Pair(dis[i],i));
                        vis[i]=true;
                        if(++cnt[i] > N+1-1) return true;
                    }
                }
            }
        }
        return false;
    }
    
    int main(){
        int F;
        scanf("%d",&F);
        for(int f=0;f<F;f++){
            fill(G[0],G[0]+MAX_N*MAX_N,20000);
            scanf("%d %d %d",&N,&M,&W);
            for(int m=0;m<M;m++){// bidirectional, might be connected by more than one path
                int S,E,T;
                scanf("%d %d %d",&S,&E,&T);
                G[S][E] = G[E][S] = (G[S][E]>10000)? T : min(G[S][E],T);
            }
            for(int w=0;w<W;w++){// one-way
                int S,E,T;
                scanf("%d %d %d",&S,&E,&T);
                G[S][E] = (G[S][E]>10000)? (-1)*T : min(G[S][E],(-1)*T);
            }
            // 辅助节点到各节点的边权设置
            G[1][N+1]=10000;
            for(int i=2;i<=N;i++) G[N+1][i]=10000;
            
            fill(dis,dis+MAX_N,999999999);
            fill(vis,vis+MAX_N,false);
            fill(cnt,cnt+MAX_N,0);
            if(SPFA(1)) printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }
    
    

    LightOJ 1074 Extended Traffic

    相较于判断是否存在负环,不同之处在于

    typedef pair<int,int> Pair;
    const int INF=0x3fffffff;
    const int MAX_N=203;
    int N;// n junction
    int M;// n roads
    int Q;// n queries
    int bsns[MAX_N];
    int G[MAX_N][MAX_N];
    int dis[MAX_N];
    int vis[MAX_N];
    int cnt[MAX_N];
    int cube(int src,int dst){// how to deal with negative val
        int tmp = bsns[dst]-bsns[src];
        return tmp*tmp*tmp;
    }
    void spfa(){
        dis[1]=0;
        priority_queue<Pair,vector<Pair>,greater<Pair> > Q;// min heap
        Q.push(Pair(dis[1],1));
        vis[1]=1;
        cnt[1]++;
        while(!Q.empty()){
            Pair p = Q.top();
            Q.pop();
            int cur = p.second;
            vis[cur]=0;
            for(int i=1;i<=N;i++){
                if(G[cur][i]==0) continue;
                if(dis[cur] + cube(cur,i) < dis[i]){
                    dis[i] = dis[cur] + cube(cur,i);
                    if(!vis[i]) {
                        // 当发现有负环时不应return,而是continue
                        // 应使负环可达的所有点的cnt都 > N-1
                        if(cnt[i]++ > N-1) continue;
                        Q.push(Pair(dis[i],i));
                        vis[i]=1;
                        // 判断是否存在负环的模板做法:
                        // if(cnt[i]++ > N-1) return;
                    }
                }
            }
        }
        return;
    }
    int main(){
        int T;
        scanf("%d",&T);
        for(int t=1;t<=T;t++){
            fill(G[0],G[0]+MAX_N*MAX_N,0);fill(dis,dis+MAX_N,INF);fill(vis,vis+MAX_N,0);
            fill(cnt,cnt+MAX_N,0);
            scanf("%d",&N);
            for(int n=1;n<=N;n++) scanf("%d",&bsns[n]);
            scanf("%d",&M);
            for(int m=1;m<=M;m++){
                int src,dst; scanf("%d %d",&src,&dst);
                G[src][dst]=1;// uni-directional
            }
            spfa();
            printf("Case %d:
    ", t);
            scanf("%d",&Q);
            for(int q=0;q<Q;q++){
                int x; scanf("%d",&x);
                // total earning less than 3 or unreachable
                // 事实上述题目给的要求比较隐晦,没直接说负环输出“?”
                // 若存在负环,dis无定义(-∞),因此判断条件还要加上:cnt[x]>N-1
                if(dis[x]<3 || dis[x]==INF ||cnt[x]>N-1) printf("?
    ");
                else printf("%d
    ", dis[x]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    centos7启动redis命令
    临时和永久关闭Selinux
    坑人的Mysql5.7 (默认不支持Group By语句)(转)
    修改docker容器参数
    FastDFS常用命令
    SpringBoot集成RabbitMQ消息队列搭建与ACK消息确认入门
    git忽略.idan目录
    springboot2.x接口返回中文乱码
    解决ssh连接linux服务器速度慢
    基于SSD固态硬盘的数据库性能优化
  • 原文地址:https://www.cnblogs.com/chengyh23/p/14585366.html
Copyright © 2011-2022 走看看