zoukankan      html  css  js  c++  java
  • hdu 4735 Little Wish~ lyrical step~(DLX)

    题目链接:hdu 4735 Little Wish~ lyrical step~

    题意:

    有n个节点的树,每个节点可能是男孩,可能是女孩,节点之间有距离,现在要让所有的女孩周围距离D之内有男孩,问最小需要交换多少次男孩和女孩的位置。

    题解:

    把每个节点对小于D距离的全部link起来,然后DLX爆艹,意义就是选n个节点去覆盖全部节点,如果这个节点是女生,那么就是要替换的点。然后不断更新答案。

      1 #include<bits/stdc++.h>
      2 #define F(i,a,b) for(int i=a;i<=b;++i)
      3 using namespace std;
      4 
      5 int boys,a[110],an;
      6 
      7 struct DLX{
      8     const static int mn=1000;
      9     #define FF(i,A,s) for(int i=A[s];i!=s;i=A[i])
     10     #define INF 0x3f3f3f3f
     11     int L[mn],R[mn],U[mn],D[mn];
     12     int size,col[mn],row[mn],s[mn],H[mn];
     13     bool vis[70];
     14     int ans[mn],cnt;
     15     void init(int m){
     16         F(i,0,m)L[i]=i-1,R[i]=i+1,U[i]=D[i]=i,s[i]=0;
     17         memset(H,-1,sizeof(H));
     18         L[0]=m;R[m]=0;size=m+1;
     19     }
     20     void link(int r,int c){
     21          U[size]=c;D[size]=D[c];U[D[c]]=size;D[c]=size;
     22          if(H[r]<0)H[r]=L[size]=R[size]=size;
     23          else L[size]=H[r],R[size]=R[H[r]],L[R[H[r]]]=size,R[H[r]]=size;
     24          s[c]++,col[size]=c,row[size]=r,size++;
     25      }
     26     void del(int c){
     27         L[R[c]]=L[c];R[L[c]]=R[c];
     28         FF(i,D,c)FF(j,R,i)U[D[j]]=U[j],D[U[j]]=D[j],--s[col[j]];
     29     }
     30     void add(int c){
     31         R[L[c]]=L[R[c]]=c;
     32         FF(i,U,c)FF(j,L,i)++s[col[U[D[j]]=D[U[j]]=j]];
     33     }
     34     bool dfs(int k){//精确覆盖
     35         if(!R[0]){
     36             cnt=k;return 1;
     37         }
     38         int c=R[0];FF(i,R,0)if(s[c]>s[i])c=i;
     39         del(c);
     40         FF(i,D,c){
     41             FF(j,R,i)del(col[j]);
     42             ans[k]=row[i];if(dfs(k+1))return 1;
     43             FF(j,L,i)add(col[j]);
     44         }
     45         add(c);
     46         return 0;
     47     }
     48     void remove(int c){FF(i,D,c)L[R[i]]=L[i],R[L[i]]=R[i];}//重复覆盖
     49     void resume(int c){FF(i,U,c)L[R[i]]=R[L[i]]=i;}
     50     int A(){//估价函数
     51         int res=0;
     52         memset(vis,0,sizeof(vis));
     53         FF(i,R,0)if(!vis[i]){
     54                 res++;vis[i]=1;
     55                 FF(j,D,i)FF(k,R,j)vis[col[k]]=1;
     56             }
     57         return res;
     58     }
     59     void dfs(int now,int cnt){//重复覆盖
     60         if(now+A()>boys||cnt>=an)return;
     61         if(!R[0])
     62         {
     63             an=cnt;
     64             return;
     65         }
     66         int temp=INF,c;
     67         FF(i,R,0)if(temp>s[i])temp=s[i],c=i;
     68         FF(i,D,c){
     69             ans[now]=row[i];
     70             remove(i);FF(j,R,i)remove(j);
     71             dfs(now+1,cnt+!a[row[i]]);
     72             FF(j,L,i)resume(j);resume(i);
     73         }
     74     }
     75 }dlx;
     76 
     77 int t,n,d,cas;
     78 
     79 int g[60],v[110],w[110],nxt[110],ed;
     80 
     81 void adg(int x,int y,int z){v[++ed]=y,w[ed]=z,nxt[ed]=g[x],g[x]=ed;}
     82 
     83 void dfs(int x,int rt,int fa=0,int dis=0)
     84 {
     85     dlx.link(rt,x);
     86     for(int i=g[x];i;i=nxt[i])
     87         if(v[i]!=fa&&dis+w[i]<=d)
     88             dfs(v[i],rt,x,dis+w[i]);
     89 }
     90 
     91 int main()
     92 {
     93     scanf("%d",&t);
     94     while(t--)
     95     {
     96         scanf("%d%d",&n,&d);
     97         boys=ed=0,dlx.init(n);
     98         memset(g,0,sizeof(g));
     99         F(i,1,n)scanf("%d",a+i),boys+=a[i];
    100         F(i,1,n-1)
    101         {
    102             int x,y,z;
    103             scanf("%d%d%d",&x,&y,&z);
    104             adg(x,y,z);
    105             adg(y,x,z);
    106         }
    107         F(i,1,n)dfs(i,i);
    108         an=INT_MAX;
    109         dlx.dfs(0,0);
    110         printf("Case #%d: %d
    ",++cas,an==INT_MAX?-1:an);
    111     }
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    linux每天一小步---grep命令详解
    linux每天一小步---xargs命令详解
    linux每天一小步---find命令详解
    linux每天一小步---tail命令详解
    linux每天一小步---head命令详解
    linux每天一小步---alias命令详解
    linux每天一小步---cat命令详解
    linux每天一小步---mv命令详解
    第十四周总结
    第十三周总结
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6360510.html
Copyright © 2011-2022 走看看