题意:
给你一个字符串,只含有数字。
你需要选择出一个子序列,使得这个子序列的权值最大。
这个子序列如果这个数字第一次出现就ans-=bx,否则就-=ax
然后如果第i个字符和第j个字符都在子序列里面,那么ans+=w[i][j]
问你最大ans是多少
官方题解:
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=15000,inf=~0U>>2,M=100100; 6 struct edge{int t,f;edge*nxt,*pair;}*g[N],*d[N],pool[M],*cur=pool; 7 struct ISAP{ 8 int n,m,i,S,T,h[N],gap[N],maxflow; 9 void init(int ss,int tt){for(S=ss,T=tt,cur=pool,i=1;i<=T;i++)g[i]=d[i]=NULL,h[i]=gap[i]=0;} 10 void add(int s,int t,int f){ 11 edge*p=cur++;p->t=t,p->f=f,p->nxt=g[s],g[s]=p; 12 p=cur++,p->t=s,p->f=0,p->nxt=g[t],g[t]=p; 13 g[s]->pair=g[t],g[t]->pair=g[s]; 14 } 15 int sap(int v,int flow){ 16 if(v==T)return flow; 17 int rec=0; 18 for(edge*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){ 19 int ret=sap(p->t,min(flow-rec,p->f)); 20 p->f-=ret;p->pair->f+=ret;d[v]=p; 21 if((rec+=ret)==flow)return flow; 22 } 23 if(!(--gap[h[v]]))h[S]=T; 24 gap[++h[v]]++;d[v]=g[v]; 25 return rec; 26 } 27 int get_ans(){ 28 for(gap[maxflow=0]=T,i=1;i<=T;i++)d[i]=g[i]; 29 while(h[S]<T)maxflow+=sap(S,inf); 30 return maxflow; 31 } 32 }G; 33 34 int t,n,v[11][2],mp[101][101],sum,cas; 35 char s[101]; 36 37 int main(){ 38 scanf("%d",&t); 39 while(t--){ 40 scanf("%d%s",&n,s+1),sum=0; 41 F(i,1,10)scanf("%d%d",&v[i][0],&v[i][1]); 42 F(i,1,n)F(j,1,n)scanf("%d",&mp[i][j]),sum+=mp[i][j]; 43 G.init(n+n*n+11,n+n*n+12); 44 F(i,1,10)G.add(n+n*n+i,G.T,v[i][1]-v[i][0]); 45 F(i,1,n) 46 { 47 G.add(n*n+i,G.T,v[s[i]-'0'+1][0]); 48 G.add(n*n+i,n*n+n+s[i]-'0'+1,inf); 49 } 50 F(i,1,n)F(j,1,n)if(mp[i][j]>0) 51 { 52 G.add(G.S,n*(i-1)+j,mp[i][j]); 53 G.add(n*(i-1)+j,n*n+i,inf); 54 G.add(n*(i-1)+j,n*n+j,inf); 55 } 56 printf("Case #%d: %d ",++cas,sum-G.get_ans()); 57 } 58 }