zoukankan      html  css  js  c++  java
  • [tc14634]ExtremeSpanningTrees

    保序回归论文题

    要求某一个边集为原图的最小生成树,这等价于非树边比所在环(指树上)的所有边小,最大生成树类似

    将这些大小关系的限制看作一张有向图,即若要求$w_{i}le w_{j}$则连边$(i,j)$,设$w_{i}$为初始边权,即要求构造$f_{i}$满足$forall (i,j)in E,f_{i}le f_{j}$,之后最小化$sum |w_{i}-f_{i}|$

    (虽然论文中要求这些大小关系构成DAG,但不构成DAG并不影响结论的证明)

    引理:定义集合$S={w_{i}}$,则存在一组最优解满足$forall i,f_{i}in S$

    证明:考虑对于一组最优解$f_{i}$,若存在$f_{i} otin S$,选择其中一个$x=f_{i}$,令$U={i|f_{i}=x}$

    考虑对于$U$中的点,同时加减1后不影响正确性(因为没有和他相同的数字,且限制包含等号),且由于$x otin S$,设加1后代价加$Delta$,则减1后代价加$-Delta$

    不难证明$min(Delta,-Delta)le 0$,因此对其进行操作不劣(特别的,当$Delta=0$时,选择加1)

    重复执行该操作,证明至多执行有限次操作(无法执行即不存在$f_{i} otin S$)

    称这样一个操作为$f(U,pm 1)$,则对于一个$U$,不可能同时存在$f(U,1)$和$f(U,-1)$

    反证法,假设存在两种操作,不妨假设先执行了$f(U,1)$,然后执行了$f(U,-1)$

    注意到若$f(U,1)$会使代价增加$Delta$,则$f(U,-1)$会使代价增加$-Delta$,且由于操作后不劣,因此两者都非负,即$Delta=0$,而当$Delta=0$时会选择加1,与假设矛盾

    称$sum(U)$为对集合$U$的操作次数,若$U$非空且$sum(U)$为无限大,则对于$xin U$,$|f_{x}-w_{x}|$也为无限大,而初始的答案为有限的,与操作不劣矛盾

    $sum_{U eqemptyset}sum(U)$即为总操作次数,由于$U$和$sum(U)$均为有限的,即结果也有限

    结论:对于一个非空区间$(a,b)$满足$Scap (a,b)=empty$,设$g_{i}$为强制$f_{i}in {a,b}$时的一组最优解,则存在一组最优解$f_{i}$满足若$g_{i}=a$则$f_{i}le a$、若$g_{i}=b$则$f_{i}ge b$

    证明:考虑一组最优解$f_{i}$,根据引理,不妨强制$f_{i}in S$,之后存在$g_{i}=a$且$f_{i}>a$($g_{i}=b$且$f_{i}<b$类似,这里就不考虑了)

    根据$f_{i}in S$且$Scap (a,b)=empty$,可得若$f_{i}>a$则$f_{i}ge b$

    令$x=min_{g_{i}=a且f_{i}ge b}f_{i}$,构造$U={i|g_{i}=a且f_{i}=x}$,再构造代价函数$f(x)=sum_{iin U}|w_{i}-x|$

    首先,我们将所有$f_{i}$(其中$iin U$)变为$y$(其中$ale yle x$)是合法的,因为这是减小,只需要考虑$j$到$i$的边,分两类讨论:

    1.$jin U$,此时由于全部改变为$y$,显然合法;

    2.$j otin U$,根据$g_{i}$和$f_{i}$为最优解,那么必然是合法的,即$g_{j}le g_{i}$且$f_{j}le f_{i}$

    进一步的,由于$g_{j}in {a,b}$因此$g_{j}=a$,由于$j otin U$因此$f_{j}<f_{i}$,那么当$f_{j}>a$则$f_{j}ge b$,同时$f_{j}<f_{i}$,那么$x$应该为$f_{j}$,矛盾

    由此,$f_{j}le ale y$,即合法

    根据$f_{i}$为最优解,因此改为$y$都不优于留在$x$,即$forall ale yle x,f(x)le f(y)$

    类似的,我们将所有$g_{i}$都变为$b$也是合法的,而$g_{i}$为最优解,即$f(a)le f(b)$

    不难发现$f(x)$是一个下凸函数,而根据上述两个性质,有$f(x)le f(b)$且$f(a)le f(b)$(其中$ale ble x$),因此只能取到等号,即$f(x)=f(a)=f(b)$

    重复执行此操作,即将$f_{i}$都变为$a$或$g_{i}$都变为$b$(两者任选一个都可以),不合法的点对数量严格减少,因此必然可以使得其不存在此类点,且两者仍为最优解,即结论成立

    根据这个结论,将所有$w_{i}$排序并离散(去除相同的位置,因为要求非空),求出$g_{i}in {w_{mid},w_{mid+1}}$的解后,即可判定(某一组)最优解$f_{i}$所有元素是小于等于$w_{mid}$还是大于等于$w_{mid+1}$,分治即可

    关于如何求出$g_{i}in {w_{mid},w_{mid+1}}$,先贪心分配$g_{i}$(不考虑合法性),将$S$连向选择$w_{mid+1}$的点,选择$w_{mid}$的点连向$T$,代价都为换为另一种后增加的代价,之后通过最小割求出最少要增大多少的代价

    对于$(i,j)in E$,不能有$g_{i}=w_{mid+1}$且$g_{j}=w_{mid}$,因此直接连边$(i,j)$,表示两者中必须修改一个,之后最跑最大流即可,并根据残余网络求出方案

    关于求最小割方案:从源点开始搜索,能被搜到(只走流量非0的边)的点即可作为最小割中与$S$相连的点,之后另一部分作为$T$相连的点,两个点集之间的边割掉即可

    时间复杂度为$o(nm^{3}log_{2}m)$,由于网络流常数较小,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 1005
      4 #define ll long long
      5 #define oo 0x3f3f3f3f
      6 #define vi vector<int>
      7 struct ji{
      8     int nex,to,len;
      9 }edge[N*N];
     10 queue<int>q;
     11 vector<int>st,v;
     12 map<int,int>mat;
     13 map<int,int>::iterator it;
     14 int E,n,head[N],vis[N],work[N],d[N],w[N],a[N],bl[N],ans[N],lim[N][N];
     15 bool cmp(int x,int y){
     16     return bl[x]<bl[y];
     17 }
     18 void init(){
     19     E=0;
     20     memset(head,-1,sizeof(head));
     21 }
     22 void add(int x,int y,int z){
     23     edge[E].nex=head[x];
     24     edge[E].to=y;
     25     edge[E].len=z;
     26     head[x]=E++;
     27 }
     28 void dfs(int k,int fa,int ed,int x,int p){
     29     if (k==ed){
     30         for(int i=0;i<st.size();i++)
     31             if (!p)lim[st[i]][x]=1;
     32             else lim[x][st[i]]=1;
     33     }
     34     for(int i=head[k];i!=-1;i=edge[i].nex)
     35         if (edge[i].to!=fa){
     36             st.push_back(edge[i].len);
     37             dfs(edge[i].to,k,ed,x,p);
     38             st.pop_back();
     39         }
     40 }
     41 bool bfs(){
     42     memset(d,oo,sizeof(d));
     43     d[0]=0;
     44     q.push(0);
     45     while (!q.empty()){
     46         int k=q.front();
     47         q.pop();
     48         for(int i=head[k];i!=-1;i=edge[i].nex)
     49             if ((edge[i].len)&&(d[edge[i].to]==oo)){
     50                 d[edge[i].to]=d[k]+1;
     51                 q.push(edge[i].to);
     52             }
     53     }
     54     return d[n+1]<oo;
     55 }
     56 int dfs(int k,int s){
     57     if (k>n)return s;
     58     for(int &i=work[k];i!=-1;i=edge[i].nex)
     59         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
     60             int p=dfs(edge[i].to,min(s,edge[i].len));
     61             if (p){
     62                 edge[i].len-=p;
     63                 edge[i^1].len+=p;
     64                 return p;
     65             }
     66         }
     67     return 0;
     68 }
     69 void dinic(){
     70     while (bfs()){
     71         memcpy(work,head,sizeof(work));
     72         while (dfs(0,oo));
     73     }
     74 }
     75 void dfs(int k){
     76     if (vis[k])return;
     77     vis[k]=1;
     78     for(int i=head[k];i!=-1;i=edge[i].nex)
     79         if (edge[i].len)dfs(edge[i].to);
     80 }
     81 void dfs(int l,int r,int x,int y){
     82     if (x==y){
     83         for(int i=l;i<=r;i++)ans[a[i]]=v[x];
     84         return;
     85     }
     86     int mid=(x+y>>1);
     87     init();
     88     for(int i=l;i<=r;i++){
     89         int wx=abs(w[a[i]]-v[mid]),wy=abs(w[a[i]]-v[mid+1]);
     90         if (wx>wy){
     91             bl[a[i]]=1;
     92             add(0,i+1,wx-wy);
     93             add(i+1,0,0);
     94         }
     95         else{
     96             bl[a[i]]=0;
     97             add(i+1,n+1,wy-wx);
     98             add(n+1,i+1,0);
     99         }
    100     }
    101     for(int i=l;i<=r;i++)
    102         for(int j=l;j<=r;j++)
    103             if (lim[a[i]][a[j]]){
    104                 add(i+1,j+1,oo);
    105                 add(j+1,i+1,0);
    106             }
    107     dinic();
    108     memset(vis,0,sizeof(vis));
    109     dfs(0);
    110     assert(!vis[n+1]);
    111     for(int i=head[0];i!=-1;i=edge[i].nex)
    112         if (!vis[edge[i].to])bl[a[edge[i].to-1]]=0;
    113     for(int i=head[n+1];i!=-1;i=edge[i].nex)
    114         if (vis[edge[i].to])bl[a[edge[i].to-1]]=1;
    115     sort(a+l,a+r+1,cmp);
    116     for(int i=l;i<=r+1;i++){
    117         if ((bl[a[i]])||(i>r)){
    118             if (l<i)dfs(l,i-1,x,mid);
    119             if (i<=r)dfs(i,r,mid+1,y);
    120             return;
    121         }
    122     }
    123 }
    124 class ExtremeSpanningTrees{
    125     public:
    126     ll minTime(vi ea,vi eb,vi ec,vi mn,vi mx){
    127         n=ea.size();
    128         init();
    129         for(int i=0;i<mn.size();i++){
    130             add(ea[mn[i]],eb[mn[i]],mn[i]);
    131             add(eb[mn[i]],ea[mn[i]],mn[i]);
    132             vis[mn[i]]=1;
    133         }
    134         for(int i=0;i<n;i++)
    135             if (!vis[i])dfs(ea[i],-1,eb[i],i,0);
    136         init();
    137         memset(vis,0,sizeof(vis));
    138         for(int i=0;i<mx.size();i++){
    139             add(ea[mx[i]],eb[mx[i]],mx[i]);
    140             add(eb[mx[i]],ea[mx[i]],mx[i]);
    141             vis[mx[i]]=1;
    142         }
    143         for(int i=0;i<n;i++)
    144             if (!vis[i])dfs(ea[i],-1,eb[i],i,1);
    145         for(int i=0;i<n;i++)mat[w[i]=ec[i]]=1;
    146         for(it=mat.begin();it!=mat.end();it++)v.push_back((*it).first);
    147         for(int i=0;i<n;i++)a[i]=i;
    148         dfs(0,n-1,0,v.size()-1);
    149         for(int i=0;i<n;i++)
    150             for(int j=0;j<n;j++)
    151                 if (lim[i][j])assert(ans[i]<=ans[j]);
    152         ll sum=0;
    153         for(int i=0;i<n;i++)sum+=abs(ans[i]-w[i]);
    154         return sum;
    155     }
    156 };
    View Code
  • 相关阅读:
    FastJson中JSONObject用法
    复盘项目模板
    java Enum 类型
    Java List集合总结
    Spring boot 使用Slf4j 日志
    java.lang.reflect.UndeclaredThrowableException
    Intellij IDEA 中使用 Debug
    Java 13位时间戳转换日期格式
    Java 时间格式转换
    Spring boot 自定义注解
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14262519.html
Copyright © 2011-2022 走看看