http://acm.hdu.edu.cn/showproblem.php?pid=5772
最大权闭合子图。
得到价值w[i][j]的条件是选了i,j这两个位置的字符。选择位置的i字符花费为
第一次选s[i]:a[s[i]] 不是第一次选s[i]:b[s[i]]
所以对于选i位置字符前提为选了花费为b[s[i]]-a[s[i]]的字符i。
得到上面的关系图后然后就是普通的最大权闭合子图问题,直接求解即可。

1 #include<cstdio> 2 #include<cstring> 3 #define M 120010 4 #define N 6010 5 #define inf 1000000000 6 int len[M <<1],e[M <<1],nex[M <<1],other[M <<1],head[N],last[N],d[N],num[N]; 7 int te,sum,_,j,num1,num2,w[110][110],a[11],b[11],m,n,i,ans,tot,ss,tt,ee,u,v,c; 8 char s[110]; 9 int init() 10 { 11 memset(head,0,sizeof(head)); 12 memset(num,0,sizeof(num)); 13 memset(d,0,sizeof(d)); 14 ans=ee=0; 15 } 16 int min(int a,int b) 17 { 18 return a<b?a:b; 19 } 20 void add(int u,int v,int c) 21 { 22 //printf("%d %d %d ",u,v,c); 23 other[++ee]=ee+1; 24 e[ee]=v;nex[ee]=head[u];head[u]=ee;len[ee]=c; 25 other[++ee]=ee-1; 26 e[ee]=u;nex[ee]=head[v];head[v]=ee;len[ee]=0; 27 } 28 int dfs(int x,int flow) 29 { 30 int rec,j,p; 31 if (x==tt) return flow; 32 rec=0;j=last[x]; 33 while (j!=0) 34 { 35 if (len[j]>0 && d[x]==d[e[j]]+1) 36 { 37 last[x]=j; 38 p=dfs(e[j],min(len[j],flow-rec)); 39 len[j]-=p;len[other[j]]+=p; 40 rec+=p; 41 if (rec==flow) return rec; 42 } 43 j=nex[j]; 44 } 45 if (d[ss]>tot) return rec; 46 if (--num[d[x]]==0) d[ss]=tot; 47 last[x]=head[x]; 48 num[++d[x]]++; 49 return rec; 50 } 51 int main() 52 { 53 scanf("%d",&_); 54 while (_--) 55 { 56 sum=0;init(); 57 scanf("%d",&n); 58 scanf("%s",s+1); 59 for (i=0;i<=9;i++) 60 scanf("%d%d",&a[i],&b[i]); 61 for (i=1;i<=n;i++) 62 for (j=1;j<=n;j++) 63 scanf("%d",&w[i][j]); 64 num1=1;ss=1; 65 for (i=1;i<=n;i++) 66 for (j=i+1;j<=n;j++) 67 if (w[i][j]+w[j][i]!=0) 68 { 69 add(ss,++num1,w[i][j]+w[j][i]); 70 sum+=w[i][j]+w[j][i]; 71 } 72 num2=1;tt=num1+n+11; 73 for (i=1;i<=n;i++) 74 for (j=i+1;j<=n;j++) 75 if (w[i][j]+w[j][i]!=0) 76 { 77 add(++num2,num1+i,inf); 78 add(num2,num1+j,inf); 79 } 80 for (i=1;i<=n;i++) 81 { 82 add(num1+i,num1+n+s[i]-'0'+1,inf); 83 add(num1+i,tt,a[s[i]-'0']); 84 } 85 for (i=0;i<=9;i++) 86 add(num1+n+i+1,tt,b[i]-a[i]); 87 tot=num[0]=tt; 88 for (i=ss;i<=tt;i++) 89 last[i]=head[i]; 90 while (d[ss]<tot) 91 ans+=dfs(ss,2147483647); 92 printf("Case #%d: %d ",++te,sum-ans); 93 } 94 return 0; 95 96 }
Run ID | Submit Time | Judge Status | Pro.ID | Exe.Time | Exe.Memory | Code Len. | Language | Author |
17819971 | 2016-07-29 15:40:45 | Accepted | 5772 | 15MS | 2052K | 2416 B | G++ | lbz007 |