POJ-3169-差分约束

根据题意可得:关系友好时,BL-AL<=DL。关系不友好时,BD-AD>=DD(一定要注意题目说明了牛是按照编号站的,也就是递增的,所以方程都是大的牛位置减去小的牛位置)。那么发现这个是个差分约束系统,即:BL-AL<=DL,AD-BD<=-DD。那么以此建图,求出有负权最短路即可。

这里再说下差分约束系统,就是几个只含两个未知数,并且形如X-Y<=D这种形式的方程组。

当求最小值时,统一化成X-Y>=D,再求最长路即可。

差分约束系统:https://blog.csdn.net/consciousman/article/details/53812818

bellman-ford算法:这里顺带讲一下几个bellman-ford注意的点。

inq数组用来判断节点是否在队列内,为的是防止在记录出现次数的时候会多记录

松弛的时候有一个dis[u]<INF判断,这是防止用没有松弛过的点去松弛

#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

#define INF 0x3f3f3f3f

using namespace std;

const int maxn=1e3+10;
int n,ml,md,u,v,w;
int dis[maxn],inq[maxn],cnt[maxn];

struct P
{
    int to,cost;
};

vector<P> edge[maxn];

int bellman_ford()
{
    queue<int> qu;
    memset(inq,0,sizeof(inq));
    memset(cnt,0,sizeof(cnt));
    memset(dis,INF,sizeof(dis));
    dis[1]=0;
    inq[1]=1;
    qu.push(1);
    while(!qu.empty())
    {
        int u=qu.front();
        qu.pop();
        inq[u]=0;
        for(int i=0; i<edge[u].size(); i++)
        {
            P v=edge[u][i];
            if(dis[u]<INF && dis[v.to]>dis[u]+v.cost)
            {
                dis[v.to]=dis[u]+v.cost;
                if(!inq[v.to])
                {
                    qu.push(v.to);
                    inq[v.to]=1;
                    if(++cnt[v.to]>n) return -1;//存在负环,即无解
                }
            }
        }
    }
    if(dis[n]==INF) return -2;//没有最短路,即无穷大
    else return dis[n];
}

int main()
{
    scanf("%d%d%d",&n,&ml,&md);
    for(int i=1; i<=ml; i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        edge[u].push_back(P{v,w});
    }
    for(int i=1; i<=md; i++)//不友好的关系反向建边
    {
        scanf("%d%d%d",&u,&v,&w);
        edge[v].push_back(P{u,-w});
    }
    printf("%d\n",bellman_ford());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/alusang/article/details/80389057
今日推荐