hdu3592(差分约束)

Nowadays, many people want to go to Shanghai to visit the World Exhibition. So there are always a lot of people who are standing along a straight line waiting for entering. Assume that there are N (2 <= N <= 1,000) people numbered 1..N who are standing in the same order as they are numbered. It is possible that two or more person line up at exactly the same location in the condition that those visit it in a group. 

There is something interesting. Some like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of X (1 <= X <= 10,000) constraints describes which person like each other and the maximum distance by which they may be separated; a subsequent list of Y constraints (1 <= Y <= 10,000) tells which person dislike each other and the minimum distance by which they must be separated. 

Your job is to compute, if possible, the maximum possible distance between person 1 and person N that satisfies the distance constraints. 

Input

First line: An integer T represents the case of test. 

The next line: Three space-separated integers: N, X, and Y. 

The next X lines: Each line contains three space-separated positive integers: A, B, and C, with 1 <= A < B <= N. Person A and B must be at most C (1 <= C <= 1,000,000) apart. 

The next Y lines: Each line contains three space-separated positive integers: A, B, and C, with 1 <= A < B <= C. Person A and B must be at least C (1 <= C <= 1,000,000) apart. 

Output

For each line: A single integer. If no line-up is possible, output -1. If person 1 and N can be arbitrarily far apart, output -2. Otherwise output the greatest possible distance between person 1 and N.

Sample Input

1
4 2 1
1 3 8
2 4 15
2 3 4

Sample Output

19

题意:求符合题意的最小集合的元素个数
题目要求的是求的最短路,
则对于 不等式  f(b)-f(a)>=c,建立 一条 b 到 a 的边 权值为 c,则求的最长路 即为 最小值(集合)
并且有隐含条件:0<=f(a)-f(a-1)<=1  则有边权关系(a,a-1,0)以及(a-1,a,-1);
将源点到各点的距离初始化为INF(无穷大),其中之1为0,最终求出的最短路满足 它们与该点之间相互差值最大
差分约束
 在实际的应用中,一般使用SPFA(Shortest Path Fast Algorithm)算法来实现。
  差分约束系统中源点到每个点的距离确定
  关于Dist[]的初始化化
  1.如果将源点到各点的距离初始化为0,最终求出的最短路满足 它们之间相互最接近了
  2.如果将源点到各点的距离初始化为INF(无穷大),其中之1为0,最终求出的最短路满足 它们与该点之间相互差值最大。
  3.差分约束系统的确立要根据自己确定的约束条件,从约束点走向被约束点
  连边一般有两种方法,第一种是连边后求最长路的方法,第二种是连边后求最短路的方法。
  例:d[x]-d[y]>=Z
  如果想连边后求最长路 那么将不等式变形为这种形式 d[x]>=d[y]+z y---x连一条权值为z的边
  求最短路则变形成d[y]<=d[x]-z x---y连一条权值为-z的边。
  如果是别的不等式,也可以根据情况变形。但是要保证的是 两个变量(x,y)的系数一定要是正的。而常量则不一定。
第一:
感觉难点在于建图
第二:
①:对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值
②:对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值
③:存在负环的话是无解
④:求不出最短路(dist[ ]没有得到更新)的话是任意解
第三:
一种建图方法:
设x[i]是第i位置(或时刻)的值(跟所求值的属性一样),那么把x[i]看成数列,前n项和为s[n],则x[i] = s[i] - s[i-1];
那么这样就可以最起码建立起类似这样的一个关系:0 <= s[i] - s[i-1] <= 1;
其他关系就要去题目探索了

 在这里可能会有疑惑,最大距离为什么是求最短路。

因为你是吧题目的边转化成了s[i]-s[j]>d;的形式。

 for(int i=2;i<=n;i++){
            addEdge(i,i-1,0);
        }别忘了添加这几条边。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXN (50000+10)
using namespace std;
struct Edge
{
    int from, to, dd,next;
    Edge(){}
    Edge(int fro,int t,int d,int net):from(fro),to(t),dd(d),next(net){}
}edge[3*MAXN];
int head[MAXN], edgenum;
bool vis[MAXN];
int dist[MAXN];
int tot[MAXN];
int n;
void init()
{
    edgenum = 0;
    memset(head,-1,sizeof(head));
}
void addEdge(int u, int v,int dist)
{
    Edge E = Edge(u, v, dist,head[u]);
    edge[edgenum] = E;
    head[u] = edgenum++;
}
int SPFA(int s, int *d)
{
    queue<int> Q;
    memset(vis,false,sizeof(false));
    memset(tot,0,sizeof(tot));
    tot[s]=1;
    d[s] = 0;
    vis[s] = true;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            Edge E = edge[i];
            if(d[E.to] > d[u] + E.dd)
            {
                d[E.to] = d[u] + E.dd;
                if(!vis[E.to])
                {
                    tot[E.to]++;
                    if(tot[E.to]>n)
                    {
                        return 0;
                    }
                    vis[E.to] = true;
                    Q.push(E.to);

                }
            }
        }
    }
    return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
    init();
     memset(dist,INF,sizeof(dist));
     int x,y;
     scanf("%d%d%d",&n,&x,&y);
     for(int i=1;i<=x;i++)
     {
         int a,b,c;
         scanf("%d%d%d",&a,&b,&c);
         addEdge(a,b,c);
     }
     for(int i=1;i<=y;i++)
     {
         int a,b,c;
          scanf("%d%d%d",&a,&b,&c);
          addEdge(b,a,-c);
     }
     for(int i=2;i<=n;i++){
			addEdge(i,i-1,0);
		}
     if(SPFA(1,dist)==0)
     {
         printf("-1\n");
     }
     else
     {
         if(dist[n]==INF)
         {
             printf("-2\n");
         }
         else
         {
             printf("%d\n",dist[n]);
         }
     }
}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值