• POJ 3169 Layout(差分约束 线性差分约束)


    题意:

    有N头牛, 有以下关系:

    (1)A牛与B牛相距不能大于k

    (2)A牛与B牛相距不能小于k

    (3)第i+1头牛必须在第i头牛前面

    给出若干对关系(1),(2)

    求出第N头牛与第一头牛的最长可能距离, 若无解输出-1, 若无限长输出-2

    分析:

    3个关系对应的 <= 式子是:

    dis[b] - dis[a] <= d(1)

    dis[a] - dis[b] <= -d(2)

    dis[i] - dis[i+1] <= -1(2)

    目标式:dis[N] - dis[1] <= T

    要求这个T就是建好图后跑源点为1的最短路, 有负权环路则无解输出-1, 不连通则输出-2(无约束关系)。

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <cstring>
    #include <cmath>
    #include <iomanip>
    #define rep(i,a,b) for(int i = a; i < b;i++)
    #define _rep(i,a,b) for(int i = a; i <= b;i++)
    using namespace std;
    const int inf = 1e9 + 7;
    const int maxn = 1000 + 7;
    int n , m;
    struct edge{
        int to , d;
        edge(int _to, int _d): to(_to), d(_d){}
    };
    vector<edge> G[maxn];
    void add_edge(int u, int v, int d){
        G[u].push_back(edge(v,d));
    }
    int N , ML, MD;
    int dis[maxn], enter_cnt[maxn];
    int spfa(){
        fill(dis, dis+maxn, inf);
        memset(enter_cnt, 0, sizeof(enter_cnt));
        bool vis[maxn];
        memset(vis, 0, sizeof(vis));
    
        queue<int> q;
        vis[1] = 1;
        dis[1] = 0;
        q.push(1);
        ++enter_cnt[1];
    
        while(!q.empty()){
            int u = q.front();
            rep(i,0,G[u].size()){
                int v = G[u][i].to, d = G[u][i].d;
                if(dis[v] > dis[u] + d){
                    dis[v] = dis[u] + d;
                    if(!vis[v]){
                        if(++enter_cnt[v] >= N) return -1;//入队次数大于等于N代表存在负权环路
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
            vis[u] = 0;
            q.pop();
        }
        return dis[N]; 
    }
    int main(){
        cin >> N >> ML >> MD;
        rep(i,0,ML){
            int a, b, d;
            cin >> a >> b >> d; //dis[b] - dis[a] <= d
            add_edge(a,b,d);
        }
        rep(i,0,MD){
            int a, b, d;
            cin >> a >> b >> d; // dis[b] - dis[a] >= d  ->  dis[a] - dis[b] <= -d
            add_edge(b,a,-d);
        }
        rep(i,1,N){ //dis[i+1] - dis[i] >= 1 ->  dis[i] - dis[i+1] <= -1
            add_edge(i+1,i,-1);
        }
        int ans = spfa();
        if(ans == -1){
            printf("-1
    ");
        }else if(ans == inf){
            printf("-2
    ");
        }else printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    动态横向(水平)合并Repeater数据行DataItem的列
    动态绑数据(Repeater控件HeaderTemplate和ItemTemplate)
    动态横向(水平)合并GridView数据行DataRow的列
    动态绑数据(GridView控件Header和ItemTemplate)
    用具体列名替代星号
    如何实现数据行转换列显示
    用LINQ获取XML节点数据
    从字符串中获取XML节点数据
    字符串创建XML文档
    根据Attribute值条件对XML文档进行修改
  • 原文地址:https://www.cnblogs.com/Jadon97/p/8353598.html
Copyright © 2020-2023  润新知