zoukankan      html  css  js  c++  java
  • 差分约束

    poj3159

    题意:n个人,m个信息,每行的信息是3个数字,A,B,C,表示B比A多出来的糖果不超过C个,问你,n号人最多比1号人多几个糖果

    思路:对应最短路模型,在松弛完最短路后则变为  d[v] <= d[u] + w  ,转化为  d[v] - d[u] <= w,这个和上面的 B - A <= C 是相同的模式 , 因此建图的时候A和B连一条有向边 , 边权为C,以1为起点,n为终点跑一遍最短路即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int maxn=150010;
    const int INF=0x3f3f3f3f;
    int head[maxn];
    bool vis[maxn];
    
    int Q[maxn];//堆栈
    int dist[maxn];
    
    int n,m;
    int a,b,c,tol;
    
    struct Edge
    {
        int to;
        int v;
        int next;
    }edge[maxn];
    
    void addedge(int a,int b,int v)
    {
        edge[tol].to=b;
        edge[tol].v=v;
        edge[tol].next=head[a];
        head[a]=tol++;
    }
    
    void SPFA(int start,int n)
    {
        int top=0;
        for(int v=1;v<=n;v++)
        {
            if(v==start)
            {
                Q[top++]=v;
                vis[v]=true;
                dist[v]=0;
            }
            else
            {
                vis[v]=false;
                dist[v]=INF;
            }
        }
        while(top!=0)
        {
            int u=Q[--top];
            vis[u]=false;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dist[v]>dist[u]+edge[i].v)
                {
                    dist[v]=dist[u]+edge[i].v;
                    if(!vis[v])
                    {
                        vis[v]=true;
                        Q[top++]=v;
                    }
                }
            }
        }
    }
    
    int main()
    {
        memset(head,-1,sizeof(head));
    
        scanf("%d%d",&n,&m);
        tol=0;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,c);
        }
        SPFA(1,n);
        printf("%d
    ",dist[n]);
        return 0;
    }

    poj3169

    一共有n头牛,有ml个关系好的牛的信息,有md个关系不好的牛的信息,对应输入的第一行的三个元素,接下来ml行,每行三个元素A,B,D,表示A牛和B牛相距不希望超过D,接下来md行,每行三个元素A,B,D表示A牛和B牛的相距至少要有D才行。求1号牛和n号牛的最大距离,如果距离无限大输出-2,如果无解输出-1。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int maxn=20020;
    const int INF=0x3f3f3f3f;
    int head[maxn];
    bool vis[maxn];
    int cnt[maxn];
    int Q[maxn];//堆栈
    int dist[maxn];
    
    int n,m,ml;
    int a,b,c,tol;
    
    struct Edge
    {
        int to;
        int v;
        int next;
    }edge[maxn];
    
    void addedge(int a,int b,int v)
    {
        edge[tol].to=b;
        edge[tol].v=v;
        edge[tol].next=head[a];
        head[a]=tol++;
    }
    
    bool SPFA(int start,int n)
    {
        int rear=0,frot=0;
        for(int v=1;v<=n;v++)
        {
            if(v==start)
            {
                Q[rear++]=v;
                vis[v]=true;
                cnt[v]=1;
                dist[v]=0;
            }
            else
            {
                vis[v]=false;
                dist[v]=INF;
                cnt[v]=0;
            }
        }
        while(rear!=frot)
        {
            int u=Q[frot++];
            vis[u]=false;
            if(frot>=maxn) frot=0;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dist[v]>dist[u]+edge[i].v)
                {
                    dist[v]=dist[u]+edge[i].v;
                    if(!vis[v])
                    {
                        vis[v]=true;
                        Q[rear++]=v;
                        if(rear>=maxn) rear=0;
                        if(++cnt[v]>n) return false;
                    }
                }
            }
        }
        return true;
    }
    
    int main()
    {
        memset(head,-1,sizeof(head));
    
        while(~scanf("%d%d%d",&n,&m,&ml))
        {
            tol=0;
            while(m--)
            {
                scanf("%d%d%d",&a,&b,&c);
                 if(a>b)swap(a,b);
                addedge(a,b,c);
            }
            while(ml--)
            {
                scanf("%d%d%d",&a,&b,&c);
                if(a<b) swap(a,b);
                addedge(a,b,-c);
            }
            if(!SPFA(1,n)) printf("-1
    ");
            else if(dist[n]==INF) printf("-2
    ");
            else printf("%d
    ",dist[n]);
        }
        
        return 0;
    }
  • 相关阅读:
    alg--动态规划(dynamic planning)
    alg--分治法
    汇编-理解call,ret
    汇编--实验7
    leetCode笔记--binary tree
    leetCode笔记--(1)
    C#获取当前路径的方法如下
    VS2013 快捷键 与 RESHARPER 冲突
    使用Visual Studio 2013进行单元测试--初级篇
    VS 插件
  • 原文地址:https://www.cnblogs.com/Fy1999/p/9556186.html
Copyright © 2011-2022 走看看