zoukankan      html  css  js  c++  java
  • 差分约束

    一般地,差分约束系统分两类:求最大差和最小差

      1. 求最小差 
        建立形如 A+B<=C 的不等式,在原图中添加边 (A, C) 边权为 B ,对建好的图跑最长路,如果存在负环,无解(判断条件为某点被更新了 n 次),n 为图中点的数量
      2. 求最大差 
        建立形如 A+B>=C 的不等式,在原图中添加边 (A, C) 边权为 B ,对建好的图跑最短路,如果存在负环,无解(判断条件为某点被更新了 n 次),n 为图中点的数量

    原因如下:

    对于线性规划问题,上述不等式的特点就是式子的左右两边都只有 1 个变量( B 为常数)。这与图上的最短路是类似的。记从起点 s 出发,到各个定点的 v 的最短距离为 d(v),因此对于每条权值为 w 的边 e =(v,u),都有 d(v)+ w >= d(u)成立。反之,在满足全部这些约束的不等式的 d 中,d(v)- d(s)的最大值就是从 s 到 v 的最短距离。需要注意的是这里不是最小值,而是最大值对应着最小距离。


    HDU1304

    题意:
    给你 n 个区间 [Ai, Bi],每一个集合有一个指标Ci。求一个集合,使得这个集合至少涵盖每个区间内的 Ci 个数字。
    问:满足上面条件的集合的最短长度是多少?

    解法:

    设 f(b) 为区间 [0,b] 之间包含的集合元素的个数,则对于不等式 f(b)-f(a-1) >= c ,建立 一条 b 到 a-1 的边 权值为 c。

    除此之外还有隐含条件:0<=f(a)-f(a-1)<=1 则有边权关系 (a,a-1,0) 以及 (a-1,a,-1);基于这三个不等式建图,则求的最长路即为最小值(集合) 。

    因为这些点是从 0 开始的,所以我们将所有点的初始值都增加 1。

    除此之外,我们还要建立一个源点与上述系统相连,由于隐含条件的存在这里就不需要了。

    注意是多组数据。。mmp

     1 struct Edge {
     2     int from, to, w, next;
     3 } e[500001];
     4 int head[MAXN], vis[MAXN];
     5 int dist[MAXN];
     6 int N, m, tot;
     7 int l = INF, r = -1;
     8 
     9 void add_edge(int i, int j, int w) {
    10     e[tot].from = i, e[tot].to = j, e[tot].w = w;
    11     e[tot].next = head[i];
    12     head[i] = tot++;
    13 }
    14 
    15 void SPFA(int s) {
    16     queue<int> q;
    17     memset(dist, -63, sizeof(dist));
    18     memset(vis, false, sizeof(vis));
    19     q.push(s);
    20     dist[s] = 0;
    21     while (!q.empty()) {
    22         int u = q.front();
    23         q.pop();
    24         vis[u] = false;
    25         for (int i = head[u]; i != -1; i = e[i].next) {
    26             int v = e[i].to;
    27             if (dist[v] < dist[u] + e[i].w) {
    28                 dist[v] = dist[u] + e[i].w;
    29                 if (!vis[v]) {
    30                     vis[v] = true;
    31                     q.push(v);
    32                 }
    33             }
    34         }
    35     }
    36     return;
    37 }
    38 
    39 int main() {
    40 #ifndef ONLINE_JUDGE
    41     freopen("input.txt", "r", stdin);
    42 #endif
    43     int n;
    44     while (scanf("%d", &n) != EOF) {
    45         int u, v, w;
    46         tot = 0;
    47         memset(head, -1, sizeof(head));
    48         for (int i = 1; i <= n; i++) {
    49             scanf("%d%d%d", &u, &v, &w);
    50             u++, v++;
    51             add_edge(u - 1, v, w);
    52             l = min(l, u);
    53             r = max(r, v);
    54         }
    55         for (int i = l; i <= r; i++) {
    56             add_edge(i - 1, i, 0);
    57             add_edge(i, i - 1, -1);
    58         }
    59         SPFA(l - 1);
    60         printf("%d
    ", abs(dist[r]));
    61     }
    62     return 0;
    63 }

    POJ3169

    题意:有 N 只牛排成一条直线,有 ML 个牛关系好的信息 (AL BL DL),代表牛 AL 和牛 BL 之间的距离不能大于 DL;类似的,给出 DL 个牛关系不好的信息 (AD BD DD),代表牛 AD 和牛 BD 之间的距离不能大于 DD。求问牛 1 和牛 N 之间可能的最大距离,如果不存在输出 -1,结果为无限输出 -2,否则输出最大距离。

    解法:由于没有给出明确关系只给出了大小关系,考虑差分方程求解

    首先因为牛的站位和编号有关,那么我们可以得到不等式 1 :$dist[i+1] ge dist[i]$,连一条从点 i+1 到点 i 的长度为 0 的边;

    其次,根据亲密的牛的关系,我们有不等式 2 :$dist[AL] + DL ge dist[BL]$,连一条从 AL 到 BL 的长度为 DL 的边;

    再次,根据不亲密的牛的关系,有不等式3:$dist[BD] - DD ge dist[AD]$,连一条从 BD 到 AD 的长度为 -DD 的边。

    由于题目要求最大距离,也就是求最短路,注意考虑负环的情况。

     1 int N, ML, DL;
     2 struct Edge {
     3     int from, to, w, next;
     4 } e[50010];
     5 int head[MAXN], vis[MAXN];
     6 int dist[MAXN];
     7 int sum[MAXN];
     8 int n, m, tot;
     9 
    10 void add_edge(int i, int j, int w) {
    11     e[tot].from = i, e[tot].to = j, e[tot].w = w;
    12     e[tot].next = head[i];
    13     head[i] = tot++;
    14 }
    15 
    16 int SPFA(int s) {
    17     queue<int> q;
    18     for (int i = 1; i <= N; i++) dist[i] = INF, sum[i] = 0;
    19     memset(vis, false, sizeof(vis));
    20     q.push(s);
    21     dist[s] = 0;
    22     while (!q.empty()) {
    23         int u = q.front();
    24         q.pop();
    25         vis[u] = false;
    26         for (int i = head[u]; i != -1; i = e[i].next) {
    27             int v = e[i].to;
    28             if (dist[v] > dist[u] + e[i].w) {
    29                 dist[v] = dist[u] + e[i].w;
    30                 if (!vis[v]) {
    31                     vis[v] = true;
    32                     sum[v]++;
    33                     if (sum[v] > N) return false;
    34                     q.push(v);
    35                 }
    36             }
    37         }
    38     }
    39     return true;
    40 }
    41 
    42 int main() {
    43     // freopen("input.txt", "r", stdin);
    44     scanf("%d%d%d", &N, &ML, &DL);
    45     int u, v, w;
    46     tot = 0;
    47     SET(head);
    48     for (int i = 2; i <= N; i++) {
    49         add_edge(i, i - 1, 0);
    50     }
    51     for (int i = 1; i <= ML; i++) {
    52         scanf("%d%d%d", &u, &v, &w);
    53         add_edge(u, v, w);
    54     }
    55     for (int i = 1; i <= DL; i++) {
    56         scanf("%d%d%d", &u, &v, &w);
    57         add_edge(v, u, -w);
    58     }
    59     if (!SPFA(1))
    60         printf("-1
    ");
    61     else if (dist[N] == INF)
    62         printf("-2
    ");
    63     else
    64         printf("%d
    ", dist[N]);
    65     return 0;
    66 }
  • 相关阅读:
    国内的pythoner强烈建议使用豆瓣的pypi源 zz
    python3.x中的urllib模块
    idcheck.py
    17、关于hibernate的N+1问题
    16、【转】Hibernate 原汁原味的四种抓取策略
    1、SSH的整合---->将Struts2整合到Spring中
    1、利用json2html.js处理json数据
    1、Ubuntu14.04使用root登陆帐户
    2、CentOS中修改yum源
    1、在CentOS上安装Java JDK的步骤
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489834.html
Copyright © 2011-2022 走看看