标签:lse name namespace ret src click 1.0 计算 memset
好神的一道题啊!
我们发现题目中的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 }
标签:lse name namespace ret src click 1.0 计算 memset
原文地址:https://www.cnblogs.com/Ren-Ivan/p/8824117.html