zoukankan      html  css  js  c++  java
  • HDU 1384 Intervals【差分约束-SPFA】

    类型:给出一些形如ab<=k的不等式(或ab>=kab<kab>k等),问是否有解【是否有负环】或求差的极值【最短/长路径】
    例子:ba<=k1cb<=k2ca<=k3。将abc转换为节点;k1k2k3转换为边权;减数指向被减数,形成一个有向图:

    由题可得ba + cb <= k1+k2ca<=k1+k2。比较k1+k2k3,其中较小者就是ca的最大值。
    由此我们可以得知求差的最大值,即上限被约束,此时我们拿最小的限制,也就是跑最短路;反之,求差的最小值,下限被约束,我们跑最长路
    跑最短路时:d[v]<=d[u]+w
    跑最长路时:d[v]>=d[u]+w
    路径中可能会存在负边,用SPFA跑。判断负环,最短最长路均可

    题意:

    [a,b]区间内有>=c个数,计算集合里至少多个元素

    思路:

    因为数据范围 0 <= ai <= bi <= 50000,可以设s[i]为i之前元素个数【不含i】,将题意转化为差分约束,s[b+1]-s[a]>=c,防止a-1出界。

    求s[end]>=?,求下限,求最长路,注意数组初始化和d数组更新条件

    解决不连通有两个方法:

    1. 新增特殊点或在区间内以1为单位连通

    2.所有点全部入队,并标记

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int N=50005;
     9 int n,cnt;
    10 const int INF=0x3f3f3f3f;
    11 int head[N],d[N];
    12 bool vis[N];
    13 
    14 struct e{
    15     int to,next,w;
    16 }edge[N<<2]; // 有反向边
    17 
    18 void add(int u,int v,int w){
    19     edge[cnt].w=w;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;
    20 }
    21 
    22 void init(){
    23     cnt=0;
    24     memset(head,-1,sizeof(head));
    25 }
    26 
    27 void SPFA(int s)
    28 {
    29     memset(d,-INF,sizeof(d));
    30     memset(vis,0, sizeof(vis));
    31     queue<int> q;
    32     q.push(s);
    33     d[s]=0;
    34     vis[s]=1;
    35     while(q.size())
    36     {
    37         int u = q.front();q.pop();
    38         vis[u]=0;
    39         for(int i=head[u];i!=-1;i=edge[i].next)
    40         {
    41             int v=edge[i].to;
    42             int w=edge[i].w;
    43             if(d[v]<d[u]+w)
    44             {
    45                 d[v]=d[u]+w;
    46                 if(!vis[v])
    47                 {
    48                     q.push(v);
    49                     vis[v]=1;
    50                 }
    51             }
    52         }
    53     }
    54 }
    55 
    56 
    57 int main(){
    58     while(scanf("%d",&n)!=EOF) {
    59         init();
    60         int st = INF, ed = -INF;
    61         for (int i = 1; i <= n; i++) {
    62             int a, b, c;
    63             cin >> a >> b >> c;
    64             add(a, b + 1, c);
    65             st = min(st, a);
    66             ed = max(ed, b + 1);
    67         }
    68         for (int i = st; i < ed; i++) {
    69             add(i, i + 1, 0);
    70             add(i + 1, i, -1);
    71         }
    72         SPFA(st);
    73         cout << d[ed] << endl;
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    【模板时间】◆模板·III◆ 单调子序列
    【学时总结】◆学时·VII◆ 高维DP
    【例题收藏】◇例题·IV◇ Wooden Sticks
    【赛时总结】◇赛时·VI◇ Atcoder ABC-104
    【例题收藏】◇例题·III◇ 木と整数 / Integers on a Tree
    【学时总结】◆学时·VI◆ SPLAY伸展树
    【模板时间】◆模板·II◆ 树链剖分
    【赛时总结】◇赛时·V◇ Codeforces Round #486 Div3
    【例题收藏】◇例题·II◇ Berland and the Shortest Paths
    【例题收藏】◇例题·I◇ Snuke's Subway Trip
  • 原文地址:https://www.cnblogs.com/demian/p/9206407.html
Copyright © 2011-2022 走看看