• USACO 2005 December Gold


    题目链接:传送门

    题意&题解:

      1. 数从1-n排列,可以列出d[i]<=d[i+1] , 即为d[i]-d[i+1]<=0,可建立 i+1 到 i 的有向边,权值为0

      2. 给出ML行 A,B和N,表示a和b的距离不能超过N,可以列出 d[B]-d[A]<=D, 即为 d[B]-d[A]<= D,可建立A到B的有向边,权值为D

      3. 给出MD行 A,B和N,表示a和b的距离不能少于N,可以列出d[B]-d[A]>=D ,即为 d[A]-d[B]<= -D,可建立B到A的有向边,权值为-D

      最后跑一边spfa计算从1-n的最短路径

    代码:用链式前向星存图跑完超时,后来发现数组少加了n个边,加上就过了,注意多测试用例要改掉。

      链式前向星&spfa:

    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<queue>
    #define numm ch-48
    #define pd putchar(' ')
    #define pn putchar('
    ')
    #define pb push_back
    #define fi first
    #define se second
    #define fre1 freopen("1.txt","r",stdin)
    #define fre2 freopen("2.txt","w",stdout)
    using namespace std;
    template <typename T>
    void read(T &res) {
        bool flag=false;char ch;
        while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
        for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
        flag&&(res=-res);
    }
    template <typename T>
    void write(T x) {
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }
    const int maxn=110;
    const int N=1010;
    const int M=10010;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    struct edge {
        int to,w,net;
    }edge[M+N];
    int k,dis[N];
    int sum[N],head[N],vis[N];
    int que[M<<1];
    void init(int n) {
        k=0;
        for(int i=1;i<=n;i++)
            head[i]=-1,vis[i]=false,sum[i]=0,dis[i]=inf;
    }
    void add(int u,int v,int w) {
        edge[++k].to=v;
        edge[k].w=w;
        edge[k].net=head[u];
        head[u]=k;
    }
    int spfa(int n) {
        ++sum[1],dis[1]=0;
        queue<int>que;
        que.push(1);
        while(!que.empty()) {
            int u=que.front();
            que.pop();
            vis[u]=false;
            for(int i=head[u];i!=-1;i=edge[i].net) {
                int v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].w) {
                    dis[v]=dis[u]+edge[i].w;
                    if(!vis[v]) {
                        if(++sum[v]>n)
                            return -1;
                        vis[v]=true;
                        que.push(v);
                    }
                }
            }
        }
        return dis[n]==inf ? -2 : dis[n];
    }
    int main()
    {
        int n,ml,md;
        while(scanf("%d%d%d",&n,&ml,&md)!=EOF) {
            init(n);
            for(int i=1;i<=ml;i++) {    /// d[B]-d[A]<=D
                int a,b,d;
                read(a),read(b),read(d);
                add(a,b,d);
            }
            for(int i=1;i<=md;i++) {    /// d[A]-d[B]<=-D
                int a,b,d;
                read(a),read(b),read(d);
                add(b,a,-d);
            }
            for(int i=1;i<n;i++)    /// d[i]-d[i+1]<=0
                add(i+1,i,0);
            write(spfa(n));pn;
        }
        return 0;
    }
    

      动态邻接表&spfa:

    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<queue>
    #define numm ch-48
    #define pd putchar(' ')
    #define pn putchar('
    ')
    #define pb push_back
    #define fi first
    #define se second
    #define fre1 freopen("1.txt","r",stdin)
    #define fre2 freopen("2.txt","w",stdout)
    using namespace std;
    template <typename T>
    void read(T &res) {
        bool flag=false;char ch;
        while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
        for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
        flag&&(res=-res);
    }
    template <typename T>
    void write(T x) {
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }
    const int maxn=110;
    const int N=1010;
    const int M=10010;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    struct edge{ int v,w; };
    vector<edge>e[N];
    int sum[N],vis[N],dis[N];
    int spfa(int n) {
        sum[1]++;
        dis[1]=0;
        queue<int>que;
        que.push(1);
        while(!que.empty()) {
            int u=que.front();que.pop();
            vis[u]=false;
            for(int i=0;i<e[u].size();i++) {
                edge x=e[u][i];
                int v=x.v;
                if(dis[v]>dis[u]+x.w) {
                    dis[v]=dis[u]+x.w;
                    if(!vis[v]) {
                        if(++sum[v] > n) return -1;
                        que.push(v);
                        vis[v] = true;
                    }
                }
            }
        }
        return dis[n]==inf ? -2 : dis[n];
    }
    int main()
    {
        int n,ml,md;
        while(scanf("%d%d%d",&n,&ml,&md)!=EOF) {
            for(int i=1;i<=n;i++)
            vis[i]=false,dis[i]=inf,sum[i]=0,e[i].clear();
            for(int i=1;i<=ml;i++){    /// d[B]-d[A]<=D
                int a,b,d;
                read(a),read(b),read(d);
                e[a].pb((edge){b,d});
            }
            for(int i=1;i<=md;i++) {    /// d[A]-d[B]<=-D
                int a,b,d;
                read(a),read(b),read(d);
                e[b].pb((edge){a,-d});
            }
            for(int i=1;i<n;i++)    /// d[i]-d[i+1]<=0
                e[i+1].pb((edge){i,0});
            write(spfa(n)),pn;
        }
        return 0;
    }
    

      

  • 相关阅读:
    读《构建之法》8、9、10章有感
    评论
    复利计算器(4)——jQuery界面美化、自动补全
    送给搭档的“汉堡”
    MFC之TreeCtrl控件使用经验总结
    MFC绘制图片闪烁详解
    MFC 网络编程中::connect返回-1问题
    C++网络编程之select
    C++关于Condition Variable
    Mutex 和 Lock
  • 原文地址:https://www.cnblogs.com/wuliking/p/11194179.html
Copyright © 2020-2023  润新知