zoukankan      html  css  js  c++  java
  • USACO 2014 US Open Dueling GPS's /// SPFA

    题目大意:

    给定n个点m条边的有向图

    有两个GPS 分别认为 A[i]到B[i] 的一条边的花费是P[i]、Q[i]

    当当前走的边不是GPS认为的最短路上的边就会被警告

    即两个GPS都不认为是最短路上的边时 会被警告两次

    求从点1走到点n被警告次数最少是多少次

    https://blog.csdn.net/oakley_/article/details/52510465

    按P[i]反向建图 再从n跑最短路到1 然后遍历所有的边判断将不是最短路的边C[i]+1

    Q[i]也同样 最后按C[i]从1跑最短路到n 得到的就是被最少警告的次数

    为什么要反向建图跑最短路?

    因为导航系统到了点2 点3 点4...之后仍然要导航到目标点n

    那么就变成了点2到点n的最短路 点3到点n的最短路 ...

    所以反向是要使得求出dis[i]为 点i到点n的最短路

    若是正向会是 点1到点n的最短路 与要求不符

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    #define gcd(i,j) __gcd(i,j)
    #define mem(i,j) memset(i,j,sizeof(i))
    #define inc(i,j,k) for(int i=j;i<=k;i++)
    #define dec(i,j,k) for(int i=j;i>=k;i--)
    const int N=1e4+5;
    const int M=1e5+5;
    
    int n,m,C[M];
    int A[M],B[M],P[M],Q[M];
    
    struct NODE { int to,len,nt; }e[M];
    int head[N], tot;
    void init() { tot=1; mem(head,0); }
    void addE(int u,int v,int w) {
        e[tot].to=v; e[tot].len=w;
        e[tot].nt=head[u]; head[u]=tot++;
    }
    
    int dis[N];
    bool inq[N];
    void SPFA(int s) {
        mem(dis,INF);
        queue<int>q;
        while(!q.empty()) q.pop();
        dis[s]=0; q.push(s);
        while(!q.empty()) {
            int u=q.front(); q.pop();
            inq[u]=0;
            for(int i=head[u];i;i=e[i].nt) {
                int v=e[i].to;
                if(dis[v]<=dis[u]+e[i].len) continue;
                dis[v]=dis[u]+e[i].len;
                if(!inq[v]) inq[v]=1, q.push(v);
            }
        }
    }
    
    void check(int u[],int v[],int w[],int st) {
        init();
        inc(i,1,m) addE(u[i],v[i],w[i]);
        SPFA(st);
        inc(i,1,m) if(dis[v[i]]!=dis[u[i]]+w[i]) C[i]++;
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m)) {
            inc(i,1,m) scanf("%d%d%d%d",&A[i],&B[i],&P[i],&Q[i]);
            mem(C,0);
            check(B,A,P,n);
            check(B,A,Q,n);
            check(A,B,C,1);
            printf("%d
    ",dis[n]);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Python——方法
    Python——类和对象(二)
    Python——类和对象(一)
    Python——函数的高级应用
    Python——函数入门(三)
    Python——函数入门(二)
    Python——函数入门(一)
    Python——序列封包与序列解包
    min(T)方法
    max(T)方法
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10548885.html
Copyright © 2011-2022 走看看