codeforces 884F 費用流,圖解很清晰
阿新 • • 發佈:2019-01-07
程式碼:
#include<bits/stdc++.h> using namespace std; const int inf = 1e9; const int mm = 111111; const int maxn = 2999; int node,src,dest,edge; int ver[mm],flow[mm],cst[mm],nxt[mm]; int head[maxn],work[maxn],dis[maxn],q[maxn]; int tot_cost; void prepare(int _node,int _src,int _dest) { node=_node,src=_src,dest=_dest; for(int i=0; i<node; ++i)head[i]=-1; edge=0; tot_cost = 0; } void add_edge(int u,int v,int c,int cost) { ver[edge]=v,flow[edge]=c,nxt[edge]=head[u],cst[edge]=cost,head[u]=edge++; ver[edge]=u,flow[edge]=0,nxt[edge]=head[v],cst[edge]=-cost,head[v]=edge++; } int ins[maxn]; int pre[maxn]; bool Dinic_spfa() { memset(ins,0,sizeof(ins)); memset(dis,-1,sizeof(dis)); memset(pre,-1,sizeof(pre)); queue<int> Q; //int i,u,v,l,r=0; Q.push(src); dis[src] = 0,ins[src] = 1; pre[src] = -1; while(!Q.empty()){ int u = Q.front();Q.pop(); ins[u] = 0; for(int e = head[u];e != -1;e = nxt[e]){ int v = ver[e]; if(!flow[e]) continue; if(dis[v] < 0 || dis[v] > dis[u] + cst[e]){ dis[v] = dis[u] + cst[e]; pre[v] = e; if(!ins[v]) ins[v] = 1,Q.push(v); } } } return dis[dest] != -1; } int Dinic_flow() { int i,ret=0,delta=inf; while(Dinic_spfa()) { for(int i=pre[dest];i != -1;i = pre[ver[i^1]]) delta = min(delta,flow[i]); for(int i=pre[dest];i != -1;i = pre[ver[i^1]]) flow[i] -= delta,flow[i^1] += delta; ret+=delta; tot_cost += dis[dest]*delta; } return ret; } int abc[27]; int ag[111]; int val[111]; int n; int main(){ int sum = 0; scanf("%d",&n); prepare(1+26+n/2*26+n+1,0,1+26+n/2*26+n); for(int i = 1;i <= n;++i){ char c;scanf(" %c",&c); abc[c-'a'+1]++; ag[i] = c-'a'+1; } for(int i = 1;i <= n;++i){ scanf("%d",&val[i]); sum += val[i]; } for(int i = 1;i <= 26;++i) add_edge(0,i,abc[i],0); for(int i = 1;i <= 26;++i){ for(int j = 1;j <= n/2;j++){ int _a = 26+(i-1)*n/2+j; add_edge(i,_a,1,0); int f1 = j,f2 = n-j+1; if(ag[f1] == i) add_edge(_a,f1+26+26*n/2,1,0); else add_edge(_a,f1+26+26*n/2,1,val[f1]); if(ag[f2] == i) add_edge(_a,f2+26+26*n/2,1,0); else add_edge(_a,f2+26+26*n/2,1,val[f2]); } } for(int i = 1;i <= n;++i) add_edge(26+26*n/2+i,1+26+n/2*26+n,1,0); int f = Dinic_flow(); //cout<<f<<endl; cout<<sum - tot_cost<<endl; return 0; }