zoukankan      html  css  js  c++  java
  • [atARC122F]Domination

    如果一个红石头在另一个红石头的左下方(包括左和下),那么在后者的限制满足时,前者也一定满足,因此可以删去前者,再将其按照$rx_{i}$排序,即有$rx_{1}<rx_{2}<...<rx_{n}$且$ry_{1}>ry_{2}>...>ry_{n}$

    称一个蓝石头覆盖一个红石头当且今当后者在前者的左下方(包括左和下),若一个蓝石头在$(x,y)$,要使其覆盖区间$[l,r]$的红石头,所需代价即$max(rx_{r}-x,0)+max(ry_{l}-y,0)$

    下面,来考虑$k=1$的情况:

    对于一个蓝石头,注意到覆盖$[l_{1},r_{1}]$和$[l_{2},r_{2}]$的代价不小于覆盖$[l_{1},r_{2}]$的代价(其中$l_{1}le r_{1}<l_{2}le r_{2}$),因此我们不妨允许其重复使用

    由此,令$f_{i}$表示前$i$个红石头都被覆盖的最小代价,枚举上一段被覆盖的区间,即有转移
    $$
    f_{i}=min_{1le jle i}(f_{j-1}+min_{1le lle m}(max(rx_{i}-bx_{l},0)+max(ry_{j}-by_{l},0)))
    $$
    关于这个dp,可以建立下述有向图来解决——

    将每一个石头拆为两个节点,分别称为$x$坐标的节点和$y$坐标的节点

    将所有$x$坐标的节点按$x$坐标从小到大排序,每一个节点向下一个节点连边权为两者$x$坐标差值的边,向上一个节点连边权为0的边

    将所有$y$坐标的节点按$y$坐标从大到小排序,并与$x$坐标类似的连边

    将所有蓝石头$y$坐标的节点向$x$坐标的节点连边权为0的边

    此时,第$j$个红石头$y$坐标的节点到第$i$个红石头$x$坐标的节点的最短路即为
    $$
    min_{1le lle m}(max(rx_{i}-bx_{l},0)+max(ry_{j}-by_{l},0))
    $$
    (这里也允许红石头向红石头移动和蓝石头向蓝石头移动,但这类边实际上一定不优)

    将第$i$个红石头$x$坐标的节点向第$i+1$个红石头$y$坐标的节点连边权为0的边,那么第1个红石头$y$坐标的节点到第$n$个红石头$x$坐标的节点的最短路即为答案

    接下来,对于任意$k$的情况,实际上即在这张图中找到$k$条路径,且其中蓝石头$x$和$y$坐标的节点之间的连边只能被使用一次,最小化这$k$条路径的长度和

    显然这可以用网络流解决,即在此图的基础上,每条边的流量为无穷大(但蓝石头$x$和$y$坐标的节点之间的连边流量为1)且费用为边权,最终求流量为$k$的最小费用即为答案

    通过费用流的做法,即做$k$次增广,每一次增广是spfa,复杂度为$o(kn^{2})$,无法通过

    给每一个节点一个势能$h_{i}$,再将一条边的费用由$w$变为$w+h_{x}-h_{y}$,那么对于一条从$x$到$y$的路径,实际上即在原费用的基础上再加$h_{x}-h_{y}$,这显然不影响$x$到$y$的最短路

    换言之,我们只需要找到合适的$h_{i}$,使得(对于流量非0的边)$w+h_{x}-h_{y}$都非负,那么以$w+h_{x}-h_{y}$为费用求最短路,就可以使用dijkstra,复杂度即降为$o(knlog n)$

    初始由于没有负权(负权边都是反向边,流量为0),直接令$h_{i}=0$即可

    接下来每一次求完最短路后增广,会导致一些边流量由0变为非0,因此要调整$h_{i}$

    具体的,设最短路为$d_{i}$,只需要令$h'_{i}=h_{i}+d_{i}$即可,下面来证明$w+h'_{x}-h'_{y}ge 0$:

    若$(x,y)$在增广前流量非0,那么$d_{y}le d_{x}+(w+h_{x}-h_{y})$,化简后即可得$w+h'_{x}-h'_{y}ge 0$

    若$(x,y)$在增广前流量为0且增广后流量非0,即$(y,x)$被作为最短路,也即$d_{y}=d_{x}+(-w+h_{x}-h_{y})$(根据费用流的建边,$(x,y)$和$(y,x)$的费用互为相反数),化简后即可得$w+h'_{x}-h'_{y}=0$

    综上,总时间复杂度为$o(knlog n)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 400005
     4 #define ll long long
     5 #define fi first
     6 #define se second
     7 struct Edge{
     8     int nex,to,len,cost;
     9 }edge[N*6];
    10 pair<int,int>a[N];
    11 vector<pair<int,int> >vx,vy;
    12 priority_queue<pair<ll,int> >q;
    13 int E,S,T,n,m,k,x,y,head[N],vis[N],from[N];
    14 ll h[N],d[N];
    15 void add(int x,int y,int z,int w){
    16     edge[E].nex=head[x];
    17     edge[E].to=y;
    18     edge[E].len=z;
    19     edge[E].cost=w;
    20     head[x]=E++;
    21     if (E&1)add(y,x,0,-w);
    22 }
    23 bool dijkstra(){
    24     memset(d,0x3f,sizeof(d));
    25     memset(vis,0,sizeof(vis));
    26     d[S]=0;
    27     q.push(make_pair(0,S));
    28     while (!q.empty()){
    29         int k=q.top().second;
    30         q.pop();
    31         if (vis[k])continue;
    32         vis[k]=1;
    33         for(int i=head[k];i!=-1;i=edge[i].nex){
    34             ll c=edge[i].cost+h[k]-h[edge[i].to];
    35             if ((edge[i].len)&&(d[edge[i].to]>d[k]+c)){
    36                 d[edge[i].to]=d[k]+c;
    37                 from[edge[i].to]=i;
    38                 q.push(make_pair(-d[edge[i].to],edge[i].to));
    39             }
    40         }
    41     }
    42     return d[T]!=d[0];
    43 }
    44 ll dinic(){
    45     ll ans=0;
    46     for(int i=1;i<=k;i++){
    47         dijkstra();
    48         ans+=d[T]-(h[S]-h[T]);
    49         for(int i=T;i!=S;i=edge[from[i]^1].to){
    50             edge[from[i]].len--;
    51             edge[from[i]^1].len++;
    52         }
    53         for(int i=1;i<=2*(n+m);i++)h[i]+=d[i];
    54     }
    55     return ans;
    56 }
    57 int main(){
    58     scanf("%d%d%d",&n,&m,&k);
    59     memset(head,-1,sizeof(head));
    60     for(int i=1;i<=n;i++){
    61         scanf("%d%d",&x,&y);
    62         a[i]=make_pair(x,y);
    63     } 
    64     sort(a+1,a+n+1);
    65     int mx=-1,nn=0;
    66     for(int i=n;i;i--){
    67         if (a[i].se<=mx)vis[i]=1;
    68         else{
    69             mx=a[i].se;
    70             nn++;
    71         }
    72     }
    73     for(int i=1,j=0;i<=n;i++)
    74         if (!vis[i]){
    75             j++;;
    76             vx.push_back(make_pair(a[i].fi,j));
    77             vy.push_back(make_pair(a[i].se,j+nn+m));
    78             if (j<nn)add(j,j+1+nn+m,k,0);
    79         }
    80     n=nn;
    81     for(int i=1;i<=m;i++){
    82         scanf("%d%d",&x,&y);
    83         vx.push_back(make_pair(x,i+n));
    84         vy.push_back(make_pair(y,i+n+n+m));
    85         add(i+n+n+m,i+n,1,0);
    86     }
    87     sort(vx.begin(),vx.end());
    88     sort(vy.begin(),vy.end());
    89     for(int i=1;i<vx.size();i++){
    90         add(vx[i-1].se,vx[i].se,k,vx[i].fi-vx[i-1].fi);
    91         add(vx[i].se,vx[i-1].se,k,0);
    92     }
    93     for(int i=1;i<vy.size();i++){
    94         add(vy[i].se,vy[i-1].se,k,vy[i].fi-vy[i-1].fi);
    95         add(vy[i-1].se,vy[i].se,k,0);
    96     }
    97     S=1+n+m,T=n;
    98     printf("%lld",dinic());
    99 }
    View Code
  • 相关阅读:
    局部加权回归、欠拟合、过拟合(Locally Weighted Linear Regression、Underfitting、Overfitting)
    损失函数(Loss Function)
    线性回归、梯度下降(Linear Regression、Gradient Descent)
    从BSP模型到Apache Hama
    Apache Hama安装部署
    C#中的面向对象编程
    0<Double.MIN_VALUE
    Java方法的参数传递方式为: 值传递
    数据取对数的意义
    UBuntu安装配置记录
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14985631.html
Copyright © 2011-2022 走看看