bzoj4067 [Ctsc2015]gender

好神的一道题啊!

我们发现题目中的ln的贡献非常傻逼,但是我们可以发现这个东西的取值只有40个左右,于是我们可以枚举他!

枚举完了对于题里的贡献就是一个普通的最小割,采用的是文理分科的思想,与S连代表不改,与T连代表改,然后流量凑一下就可以了。

那么我们怎么判断我们枚举的值和算出来的方案是否对应呢?我们发现K很小,于是我们可以对于每一层都状压状态,然后通过上面的网络流来计算当这层状态确定时的最优解,然后最后再dp转移一下就可以了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 #define N 1050
  8 #define inf 0x3fffffff
  9 using namespace std;
 10 int e=2,head[N];
 11 struct edge{
 12     int u,v,f,next;
 13 }ed[N*N<<1];
 14 void add(int u,int v,int f){
 15     ed[e].u=u;ed[e].v=v;ed[e].f=f;
 16     ed[e].next=head[u];head[u]=e++;
 17     ed[e].u=v;ed[e].v=u;ed[e].f=0;
 18     ed[e].next=head[v];head[v]=e++;
 19 }
 20 int dep[N],S,T;
 21 bool bfs(){
 22     memset(dep,0,sizeof dep);
 23     queue<int> q;q.push(S);dep[S]=1;
 24     while(!q.empty()){
 25         int x=q.front();q.pop();
 26         for(int i=head[x];i;i=ed[i].next){
 27             if(ed[i].f&&!dep[ed[i].v]){
 28                 dep[ed[i].v]=dep[x]+1;
 29                 if(ed[i].v==T)return 1;
 30                 q.push(ed[i].v);
 31             }
 32         }
 33     }
 34     return 0;
 35 }
 36 int dfs(int x,int f){
 37     if(x==T||!f)return f;
 38     int ans=0;
 39     for(int i=head[x];i;i=ed[i].next){
 40         if(ed[i].f&&dep[ed[i].v]==dep[x]+1){
 41             int nxt=dfs(ed[i].v,min(f,ed[i].f));
 42             ans+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^1].f+=nxt;
 43         }
 44     }
 45     if(!ans)dep[x]=-1;
 46     return ans;
 47 }
 48 int dinic(){
 49     int ans=0;
 50     while(bfs())ans+=dfs(S,inf);
 51     return ans;
 52 }
 53 int cnt[20]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
 54 int n,K,m,p,c[N],id[N],x[N],y[N],a[5][55];
 55 int fa[N];
 56 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
 57 struct data{int u,v,w,x;}d[N*10];
 58 bool cmp1(data a,data b){return y[a.u]<y[b.u];}
 59 bool cmp2(int a,int b){return y[a]<y[b];}
 60 char s[N];
 61 int in[N],w[55][17],f[55][215][17],ans;
 62 void getmax(int &x,int y){x>y?x=x:x=y;}
 63 int main(){
 64     scanf("%d%d%d%d%s",&n,&K,&m,&p,s+1);
 65     S=m+1;T=S+1;
 66     register int i,j,k,l,s1,s2,l1,r1,l2,r2,V,now;
 67     for(i=1;i<=m;i++)
 68         scanf("%d",&c[i]),id[i]=fa[i]=i;
 69     for(i=1;i<=K;i++)
 70         for(j=1;j<=n;j++){
 71             scanf("%d",&a[i][j]);
 72             x[a[i][j]]=i;y[a[i][j]]=j;
 73         }
 74     for(i=1;i<=p;i++){
 75         double x;
 76         scanf("%d%d%d%lf",&d[i].u,&d[i].v,&d[i].w,&x);
 77         d[i].x=d[i].w*x;
 78         if(find(d[i].u)!=find(d[i].v))fa[fa[d[i].u]]=fa[d[i].v];
 79     }
 80     for(i=1;i<=m;i++){
 81         if(y[find(i)])y[i]=y[fa[i]];
 82         if(!y[fa[i]]&&y[i])y[fa[i]]=y[i];
 83     }
 84     for(i=1;i<=m;i++){
 85         if(!y[fa[i]])y[fa[i]]=1;
 86         y[i]=y[fa[i]];
 87     }
 88     sort(d+1,d+p+1,cmp1);
 89     sort(id+1,id+m+1,cmp2);
 90     for(l=0;l<=(n-1)*K;l++){
 91         if(!l||(floor(10*log(1.0*l))!=floor(10*log(1.0*(l+1))))){
 92             V=floor(10*log(1.0*(l+1)));
 93             for(i=1,l1=1,r1=0,l2=1,r2=0;i<=n;i++){
 94                 while(r1<p&&y[d[r1+1].u]==i)r1++;
 95                 while(r2<m&&y[id[r2+1]]==i)r2++;
 96                 for(j=0;j<(1<<K);j++){
 97                     e=2;now=head[S]=head[T]=0;
 98                     for(k=l2;k<=r2;k++)in[id[k]]=head[id[k]]=0;
 99                     for(k=l1;k<=r1;k++){
100                         now+=V*d[k].w*2;
101                         in[d[k].u]+=V*(d[k].w-d[k].x);
102                         in[d[k].v]+=V*(d[k].w-d[k].x);
103                         add(d[k].u,d[k].v,V*(d[k].w+d[k].x));
104                         add(d[k].v,d[k].u,V*(d[k].w+d[k].x));
105                     }
106                     for(k=l2;k<=r2;k++){
107                         if(!x[id[k]])add(S,id[k],c[id[k]]*2+in[id[k]]),add(id[k],T,0);
108                         else if(j&(1<<x[id[k]]-1))add(S,id[k],c[id[k]]*2+in[id[k]]),add(id[k],T,inf);
109                         else add(S,id[k],inf),add(id[k],T,0);
110                     }
111                     w[i][j]=(now-dinic())/2;
112                 }
113                 l1=r1+1;l2=r2+1;
114             }
115         }
116         memset(f,-0x3f,sizeof f);
117         for(i=0;i<(1<<K);i++)f[1][0][i]=w[1][i];
118         for(i=1;i<n;i++)
119             for(j=0;j<=l&&j<=(i-1)*K;j++)
120                 for(s1=0;s1<(1<<K);s1++)if(f[i][j][s1]!=f[0][0][0])
121                     for(s2=0;s2<(1<<K);s2++)
122                         getmax(f[i+1][j+cnt[s1^s2]][s2],f[i][j][s1]+w[i+1][s2]);
123         for(i=0;i<(1<<K);i++)ans=max(ans,f[n][l][i]);
124     }
125     printf("%d\n",ans);
126     return 0;
127 }
View Code

 

posted @ 2018-04-13 21:32  Ren_Ivan  阅读(414)  评论(4编辑  收藏  举报