• LOJ3097 SNOI2019 通信 题解


    题目链接

    费用流,当建边需要依靠位置和权值两个偏序关系时,可以用cdq分治优化建边。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 20007
      4 #define M 200007
      5 const int inf=0x3f3f3f3f;
      6 #define ll long long
      7 struct flow
      8 {
      9     int hd[N],pre[M],to[M],num,w[M],mf[N],fa[N],maf,s,t;
     10     ll f[M],dis[N],ans;
     11     bool vis[N];
     12     queue<int> q;
     13     void adde(int x,int y,int z,int l)
     14         {
     15             num++;pre[num]=hd[x];hd[x]=num;to[num]=y;w[num]=z;f[num]=l;
     16             num++;pre[num]=hd[y];hd[y]=num;to[num]=x;w[num]=0;f[num]=-l;
     17         }
     18     void Init()
     19         {
     20             num=1;
     21         }
     22     bool spfa()
     23         {
     24             memset(dis,0x3f,sizeof(dis));
     25             memset(vis,0,sizeof(vis));
     26             while(!q.empty())q.pop();
     27             int i,v,u;
     28             dis[s]=0;
     29             mf[s]=inf;
     30             q.push(s);
     31             while(!q.empty())
     32             {
     33                 v=q.front();q.pop();
     34                 vis[v]=false;
     35                 for(i=hd[v];i;i=pre[i])
     36                 {
     37                     u=to[i];
     38                     if(w[i]&&dis[v]+f[i]<dis[u])
     39                     {
     40                         dis[u]=dis[v]+f[i];
     41                         fa[u]=i;
     42                         mf[u]=min(mf[v],w[i]);
     43                         if(!vis[u])
     44                         {
     45                             vis[u]=true;
     46                             q.push(u);
     47                         }
     48                     }
     49                 }
     50             }
     51             return dis[t]<1e18;
     52         }
     53     void update()
     54         {
     55             int v=t,i,fl=mf[t];
     56             while(v!=s)
     57             {
     58                 i=fa[v];
     59                 w[i]-=fl;
     60                 w[i^1]+=fl;
     61                 v=to[i^1];
     62             }
     63             ans+=dis[t]*fl;
     64             maf+=fl;
     65         }
     66     void main()
     67         {
     68             while(spfa())
     69                 update();
     70         }
     71 }D;
     72 struct str
     73 {
     74     int a,p;
     75 }p[N],tmp[N];
     76 bool operator <(str a,str b)
     77 {
     78     return a.p<b.p;
     79 }
     80 int tot,Pre[N],Suf[N],n;
     81 void cdq(int l,int r)
     82 {
     83     if(l==r)return;
     84     int mid=l+r>>1,i;
     85     cdq(l,mid),cdq(mid+1,r);
     86     for(i=l;i<mid;i++)
     87     {
     88         ++tot;
     89         Pre[i]=tot;
     90         D.adde(tot,p[i].p+n,inf,0);
     91         D.adde(tot+1,tot,inf,p[i+1].a-p[i].a);
     92     }
     93     ++tot;
     94     Pre[mid]=tot;
     95     D.adde(tot,p[mid].p+n,inf,0);
     96     for(i=mid;i>l;i--)
     97     {
     98         ++tot;
     99         Suf[i]=tot;
    100         D.adde(tot,p[i].p+n,inf,0);
    101         D.adde(tot+1,tot,inf,p[i].a-p[i-1].a);
    102     }
    103     ++tot;
    104     Suf[l]=tot;
    105     D.adde(tot,p[l].p+n,inf,0);
    106     int j=l-1;
    107     for(i=mid+1;i<=r;i++)
    108     {
    109         while(j<mid&&p[j+1].a<p[i].a)j++;
    110         if(j>=l)D.adde(p[i].p,Pre[j],inf,p[i].a-p[j].a);
    111         if(j<mid)D.adde(p[i].p,Suf[j+1],inf,p[j+1].a-p[i].a);
    112     }
    113     i=l,j=mid+1;
    114     int k=l;
    115     while(i<=mid&&j<=r)
    116     {
    117         if(p[i].a<p[j].a)
    118             tmp[k++]=p[i++];
    119         else tmp[k++]=p[j++];
    120     }
    121     while(i<=mid)tmp[k++]=p[i++];
    122     while(j<=r)tmp[k++]=p[j++];
    123     for(i=l;i<=r;i++)
    124         p[i]=tmp[i];
    125 }
    126 int main()
    127 {
    128     int i,x,y,w;
    129     scanf("%d%d",&n,&w);
    130     for(i=1;i<=n;i++)
    131     {
    132         scanf("%d",&x);
    133         p[i]={x,i};
    134     }
    135     D.Init();
    136     D.s=2*n+1,D.t=2*n+2;
    137     tot=2*n+2;
    138     for(i=1;i<=n;i++)
    139     {
    140         D.adde(D.s,i,1,0);
    141         D.adde(i,D.t,1,w);
    142         D.adde(i+n,D.t,1,0);
    143     }
    144     sort(p+1,p+n+1);
    145     cdq(1,n);
    146     D.main();
    147     printf("%lld
    ",D.ans);
    148     return 0;
    149 }
  • 相关阅读:
    asp.net 验证正则表达式
    c语言编程题
    使用Code First创建数据模型
    c语言知识点
    rabbitmq 简单应用
    influxdb(二)
    influxdb(一)
    K8S 日志收集(六):kibana 安装
    K8S 日志收集(五):head插件安装
    K8S 日志收集(四):logstash 安装
  • 原文地址:https://www.cnblogs.com/lishuyu2003/p/11160726.html
Copyright © 2020-2023  润新知