BZOJ4218 : 不知道高到哪裡去了

Claris發表於2018-03-07

設$degi[x]$和$dego[x]$分別表示每個點的入度和出度,將線性規劃的限制寫出來:

目標函式:

$\max.\ \sum_{x=1}^n(dego[x]P[x]-degi[x]Q[x])$

限制:

$P[x]-Q[y]\leq T(x,y)-L(x,y)$

$Q[y]-P[x]\leq L(x,y)-S(x,y)$

$P[x]\leq 10^6$

$Q[x]\leq 10^6$

這是個標準型線性規劃,將其對偶,得到每條邊的兩個輔助變數$a,b$以及每個$P,Q$對應上界的輔助變數$c,d$:

目標函式:

$\min.\ \sum_{(x,y)\in E}((T(x,y)-L(x,y))a(x,y)+(L(x,y)-S(x,y))b(x,y))+\sum_{x=1}^n(10^6c[x]+10^6d[x])$

限制:

$\sum_{(x,i)\in E}a(x,i)-\sum_{(i,x)\in E}b(i,x)+c[x]\geq dego[x]$

$\sum_{(i,x)\in E}b(i,x)-\sum_{(x,i)\in E}a(x,i)+d[x]\geq -degi[x]$

將每條限制看作點,每個二元變數看作邊,在對應負係數限制連向正係數限制,流量$[0,+\infty)$,費用為在目標函式中的係數。

對於$c$和$d$,從$S$向$x$連邊,流量$[0,+\infty)$,費用$10^6$。

對於$dego[x]$,從$x$向$T$連邊,流量$[dego[x],+\infty)$,費用$0$。

對於$-degi[x]$,從$S$向$x$連邊,流量$[degi[x],degi[x]]$,再從$x$向$T$連邊,流量$[0,+\infty)$,費用$0$。

則答案就是這個圖的最小費用可行流,當出現負環時該線性規劃無界,故原問題無解。

 

#include<cstdio>
typedef long long ll;
const int N=60010,M=1000000;
const ll inf=1LL<<60;
int Case,n,m,i,degi[N],dego[N];ll tmp,ans;
int u[M],v[M],nxt[M],t,S,T,SS,TT,q[M],g[N],f[N],cnt[N];ll c[M],co[M],d[N],in[N];bool vis[N];
unsigned short l,r;
inline void add(int x,int y,ll l,ll r,ll z){
  r-=l,in[x]-=l,in[y]+=l;
  if(!r)return;
  u[++t]=x;v[t]=y;c[t]=r;co[t]=z;nxt[t]=g[x];g[x]=t;
  u[++t]=y;v[t]=x;c[t]=0;co[t]=-z;nxt[t]=g[y];g[y]=t;
}
int spfa(){
  int x,i;
  for(i=1;i<=TT;i++)d[i]=inf,vis[i]=cnt[i]=0;
  d[SS]=0;vis[SS]=1;q[l=r=0]=SS;
  while(l!=r+1){
    x=q[l++];
    if(x==TT)continue;
    vis[x]=0;
    for(i=g[x];i;i=nxt[i])if(c[i]&&co[i]+d[x]<d[v[i]]){
      d[v[i]]=co[i]+d[x];f[v[i]]=i;
      if(!vis[v[i]]){
        vis[v[i]]=1;
        cnt[v[i]]++;
        if(cnt[v[i]]>TT+5)return -1;
        q[++r]=v[i];
      }
    }
  }
  return d[TT]<inf;
}
bool solve(){
  scanf("%d%d",&n,&m);
  S=n*2+1;
  T=S+1;
  SS=T+1;
  TT=SS+1;
  for(t=i=1;i<=TT;i++)degi[i]=dego[i]=g[i]=in[i]=0;
  ans=0;
  add(T,S,0,inf,0);
  bool flag=0;
  while(m--){
    int x,y,_L,_S,_T;
    scanf("%d%d%d%d%d",&x,&y,&_L,&_S,&_T);
    if(_S>_T)flag=1;
    dego[x]++;
    degi[y]++;
    ans+=_L;
    add(y+n,x,0,inf,_T-_L);
    add(x,y+n,0,inf,_L-_S);
  }
  if(flag)return 0;
  for(i=1;i<=n;i++){
    add(S,i,0,inf,1000000);
    add(i,T,dego[i],inf,0);
    add(S,i+n,0,inf,1000000);
    add(S,i+n,degi[i],degi[i],0);
    add(i+n,T,0,inf,0);
  }
  for(i=1;i<=TT;i++){
    if(in[i]>0)add(SS,i,0,in[i],0);
    if(in[i]<0)add(i,TT,0,-in[i],0);
  }
  while(1){
    int o=spfa();
    if(!o)return 1;
    if(o==-1)return 0;
    for(tmp=inf,i=TT;i!=SS;i=u[f[i]])if(tmp>c[f[i]])tmp=c[f[i]];
    for(ans+=d[i=TT]*tmp;i!=SS;i=u[f[i]])c[f[i]]-=tmp,c[f[i]^1]+=tmp;
  }
}
int main(){
  scanf("%d",&Case);
  while(Case--)if(!solve())puts("Unlike");else printf("%lld\n",ans);
  return 0;
}

  

相關文章