差分约束

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;
}
原文地址:https://www.cnblogs.com/Fy1999/p/9556186.html