• 差分约束


    在一个差分约束系统(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
    ",g.getdist(n));
    80     }
    81     return 0;
    82 }
    View Code

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

    有》=也有《=,  大于等于的移项一下,还是跟小于等于一样的建边,有负环是无解,最短路是inf是任意解,有最短路就是唯一解

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<stack>
     6 #define mt(a,b) memset(a,b,sizeof(a))
     7 using namespace std;
     8 const int inf=0x3f3f3f3f;
     9 class Spfa { ///单源最短路o(k*ME)k~=2
    10     typedef int typec;///边权的类型
    11     static const int ME=2e4+10;///边的个数
    12     static const int MV=1e3+10;///点的个数
    13     struct E {
    14         int v,next;
    15         typec w;
    16     } e[ME];
    17     int n,le,head[MV],inque[MV],i,u,v;
    18     typec dist[MV];
    19     bool used[MV];
    20     queue<int> q;
    21 public:
    22     void init(int tn) { ///传入点的个数
    23         n=tn;
    24         le=0;
    25         for(i=0; i<=n; i++) head[i]=-1;
    26     }
    27     void add(int u,int v,typec w) {
    28         e[le].v=v;
    29         e[le].w=w;
    30         e[le].next=head[u];
    31         head[u]=le++;
    32     }
    33     bool solve(int s) { ///传入起点,存在负环返回false
    34         for(i=0; i<=n; i++) {
    35             dist[i]=inf;
    36             used[i]=true;
    37             inque[i]=0;
    38         }
    39         used[s]=false;
    40         dist[s]=0;
    41         inque[s]++;
    42         while(!q.empty()) q.pop();
    43         q.push(s);
    44         while(!q.empty()) {
    45             u=q.front();
    46             q.pop();
    47             used[u]=true;
    48             for(i=head[u]; ~i; i=e[i].next) {
    49                 v=e[i].v;
    50                 if(dist[v]>dist[u]+e[i].w) {
    51                     dist[v]=dist[u]+e[i].w;
    52                     if(used[v]) {
    53                         used[v]=false;
    54                         q.push(v);
    55                         inque[v]++;
    56                         if(inque[v]>n) return false;
    57                     }
    58                 }
    59             }
    60         }
    61         return true;
    62     }
    63     typec getdist(int id) {
    64         return dist[id];
    65     }
    66 } g;
    67 int main() {
    68     int n;
    69     int ML,MD;
    70     int a,b,c;
    71     while(~scanf("%d%d%d",&n,&ML,&MD)) {
    72         g.init(n);
    73         while(ML--) {
    74             scanf("%d%d%d",&a,&b,&c);
    75             if(a>b)swap(a,b);//注意加边顺序
    76             g.add(a,b,c);
    77             //大-小<=c ,有向边(小,大):c
    78         }
    79         while(MD--) {
    80             scanf("%d%d%d",&a,&b,&c);
    81             if(a<b)swap(a,b);
    82             g.add(a,b,-c);
    83             //大-小>=c,小-大<=-c,有向边(大,小):-c
    84         }
    85         if(!g.solve(1)) printf("-1
    ");//无解
    86         else if(g.getdist(n)==inf) printf("-2
    ");
    87         else printf("%d
    ",g.getdist(n));
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    使用 pymssql 调用存储过程
    控制input框的输入格式
    Pycharm创建指定版本的Django
    div在页面中居中显示
    odoo12--centos7搭建odoo12
    odoo12--models模型
    odoo12--创建第一个模块
    odoo12模块目录
    odoo12代码目录说明
    win10安装odoo12教程
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/4483488.html
Copyright © 2020-2023  润新知