码迷,mamicode.com
首页 > 其他好文 > 详细

差分约束

时间:2015-05-07 00:41:54      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:

在一个差分约束系统(system of difference constraints)中,线性规划矩阵A的每一行包含一个1和一个-1,A的其他所有元素都为0。因此,由Ax≤b给出的约束条件是m个差分约束集合,其中包含n个未知量,对应的线性规划矩阵A为m行n列。每个约束条件为如下形式的简单线性不等式:xj-xi≤bk。其中1≤i,j≤n,1≤k≤m。

例如,考虑这样一个问题,寻找一个5维向量x=(xi)以满足:

 

技术分享

 

这一问题等价于找出未知量xi,i=1,2,…,5,满足下列8个差分约束条件:

x1-x2≤0

x1-x5≤-1

x2-x5≤1

x3-x1≤5

x4-x1≤4

x4-x3≤-1

x5-x3≤-3

x5-x4≤-3

    该问题的一个解为x=(-5,-3,0,-1,-4),另一个解y=(0,2,5,4,1),这2个解是有联系的:y中的每个元素比x中相应的元素大5。

 
引理:设x=(x1,x2,…,xn)是差分约束系统Ax≤b的一个解,d为任意常数。则x+d=(x1+d,x2+d,…,xn+d)也是该系统Ax≤b的一个解。

 

 

http://poj.org/problem?id=3159

 

给n个人派糖果,给出m组数据,每组数据包含A,B,c  三个数,
意思是A的糖果数比B少的个数不多于c,即B的糖果数 - A的糖果数<= c 。
最后求n 比 1 最多多多少糖果。

算是裸题   v-u《=w  建有向边  u-》v  权值w  若有负环无解  

 //大-小<=c ,有向边(小,大):c

如果是大于等于的  转化一下  如下

//大-小>=c,小-大<=-c,有向边(大,小):-c

 

【解题思路】
这是一题典型的差分约束题。不妨将糖果数当作距离,把相差的最大糖果数看成有向边AB的权值,
我们得到 dis[B]-dis[A]<=w(A,B)。看到这里,我们联想到求最短路时的松弛技术,
即if(dis[B]>dis[A]+w(A,B), dis[B]=dis[A]+w(A,B)。
即是满足题中的条件dis[B]-dis[A]<=w(A,B),由于要使dis[B] 最大,
所以这题可以转化为最短路来求。
这题如果用SPFA 算法的话,则需要注意不能用spfa+queue 来求,会TLE ,而是用 spfa + stack

 我用了priority的dij   因为题目保证了有解

技术分享
 1 #include<cstdio>
 2 #include<queue>
 3 using namespace std;
 4 const int inf=0x3f3f3f3f;
 5 class Dijkstra { ///单源最短路 o(ME*log(MV))
 6     typedef int typec;///边权的类型
 7     static const int ME=2e5+10;///边的个数
 8     static const int MV=3e4+10;///点的个数
 9     struct Q {
10         int id;
11         typec w;
12         friend bool operator <(const Q &a,const Q &b) {
13             return a.w>b.w;
14         }
15     } now;
16     priority_queue<Q> q;
17     struct E {
18         int v,next;
19         typec w;
20     } e[ME];
21     int n,le,head[MV],u,v,i;
22     typec dist[MV],w;
23     bool used[MV];
24 public:
25     void init(int tn) {///传入点的个数
26         n=tn;
27         le=0;
28         for(i=0; i<=n; i++) head[i]=-1;
29     }
30     void add(int u,int v,typec w) {
31         e[le].v=v;
32         e[le].w=w;
33         e[le].next=head[u];
34         head[u]=le++;
35     }
36     void solve(int s) {///传入起点
37         for(i=0; i<=n; i++) {
38             used[i]=true;
39             dist[i]=inf;
40         }
41         dist[s]=0;
42         now.id=s;
43         now.w=0;
44         while(!q.empty()) q.pop();
45         q.push(now);
46         while(!q.empty()) {
47             now=q.top();
48             q.pop();
49             u=now.id;
50             if(used[u]) {
51                 used[u]=false;
52                 for(i=head[u]; ~i; i=e[i].next) {
53                     v=e[i].v;
54                     w=e[i].w;
55                     if(used[v]&&dist[v]>w+dist[u]) {
56                         dist[v]=w+dist[u];
57                         now.id=v;
58                         now.w=dist[v];
59                         q.push(now);
60                     }
61                 }
62             }
63         }
64     }
65     typec getdist(int id) {
66         return dist[id];
67     }
68 } g;
69 
70 int main(){
71     int n,m,u,v,w;
72     while(~scanf("%d%d",&n,&m)){
73         g.init(n);
74         while(m--){
75             scanf("%d%d%d",&u,&v,&w);
76             g.add(u,v,w);
77         }
78         g.solve(1);
79         printf("%d\n",g.getdist(n));
80     }
81     return 0;
82 }
View Code

 

 

 

差分约束

标签:

原文地址:http://www.cnblogs.com/gaolzzxin/p/4483488.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!