• BZOJ3742 : Painting


    设f[i][j]表示以i为根的子树,i与父亲之间的边染成j的最小代价

    DP的过程中转移时相当于求一个最小权匹配,用费用流即可

    感觉复杂度飞起来了…

    #include<cstdio>
    const int inf=~0U>>2,N=30000,M=1000110,MAXN=160;
    int n,x,y,i,j;
    int u[M],v[M],c[M],co[M],nxt[M],t,S,T,l,r,q[M],g[N],f[N],d[N];bool in[N];
    int G[MAXN],NXT[MAXN<<1],V[MAXN<<1],ed,dp[MAXN][MAXN];
    inline void ADD(int x,int y){V[++ed]=y;NXT[ed]=G[x];G[x]=ed;}
    inline void add(int x,int y,int z,int zo){
      u[++t]=x;v[t]=y;c[t]=z;co[t]=zo;nxt[t]=g[x];g[x]=t;
      u[++t]=y;v[t]=x;c[t]=0;co[t]=-zo;nxt[t]=g[y];g[y]=t;
    }
    inline bool spfa(){
      int x,i;
      for(i=1;i<=T;i++)d[i]=inf;
      d[S]=0;in[S]=1;l=r=M>>1;q[l]=S;
      while(l<=r){
        int x=q[l++];
        if(x==T)continue;
        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(!in[v[i]]){
            in[v[i]]=1;
            if(d[v[i]]<d[q[l]])q[--l]=v[i];else q[++r]=v[i];
          }
        }
        in[x]=0;
      }
      return d[T]<inf;
    }
    void solve(int x,int pre){
      int i,j,k,now,cnt=0;
      for(i=G[x];i;i=NXT[i])if(V[i]!=pre)solve(V[i],x),cnt++;
      if(x==1){
        if(!cnt)return;
        t=1;S=0;T=n*(cnt+1);
        for(i=0;i<=T;i++)g[i]=in[i]=0;
        for(j=1;j<n;j++)add(j,T,j!=now,0);
        for(j=n-1,i=G[x];i;j+=n-1,i=NXT[i])if(V[i]!=pre)for(add(S,++j,1,0),k=1;k<n;k++)add(j,j+k,1,dp[V[i]][k]),add(j+k,k,1,0);
        while(spfa())for(i=T;i!=S;i=u[f[i]])--c[f[i]],++c[f[i]^1],dp[x][0]+=co[f[i]];
      }else for(now=1;now<n;now++){
        dp[x][now]=now;
        if(!cnt)continue;
        t=1;S=0;T=n*(cnt+1);
        for(i=0;i<=T;i++)g[i]=in[i]=0;
        for(j=1;j<n;j++)add(j,T,j!=now,0);
        for(j=n-1,i=G[x];i;j+=n-1,i=NXT[i])if(V[i]!=pre)for(add(S,++j,1,0),k=1;k<n;k++)add(j,j+k,1,dp[V[i]][k]),add(j+k,k,1,0);
        while(spfa())for(i=T;i!=S;i=u[f[i]])--c[f[i]],++c[f[i]^1],dp[x][now]+=co[f[i]];
      }
    }
    int main(){
      scanf("%d",&n);
      for(i=1;i<n;i++)scanf("%d%d",&x,&y),ADD(x,y),ADD(y,x);
      solve(1,0);
      return printf("%d",dp[1][0]),0;
    }
    

      

  • 相关阅读:
    JSON,数组根据字段多次分组
    .net c#后台请求接口
    数组的高级应用含ES6 for of 用法
    js获取当前页面url网址信息
    资源管理神器Clover
    ES6的7个实用技巧
    单标签实现气泡三角形
    移动端--上拉加载更多
    checkbox对齐-复选框图标
    textarea显示源代码
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403212.html
Copyright © 2020-2023  润新知