很明显的费用流,不过建图还是卡住了。。。问的gb才知道怎么建图。。。
先是源点到n个串,容量是a[i],费用是0,然后是串t中包含的所有不重复字母为一个节点,从这些节点向汇点T连边,容量是当前字母的个数,费用是0。
然后是n个串向T中的字母连边,容量是a[i]中当前字母的个数,费用是i。
ps:费用流模板有问题。以至于debug了好久。。。T_T

//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; const int N = 1024; struct node { int from, to, cost, flow, next; // } g[N*N]; int S, T; int head[N], t; void init() { CL(head, -1); t = 0; } void add(int u, int v, int f, int w) { g[t].from = u; g[t].to = v; g[t].flow = f; g[t].cost = w; g[t].next = head[u]; head[u] = t++; g[t].from = v; g[t].to = u; g[t].flow = 0; g[t].cost = -w; g[t].next = head[v]; head[v] = t++; } int dis[N]; int pre[N]; bool vis[N]; queue<int> q; bool spfa() { //找最大费用 while(!q.empty()) q.pop(); for(int i = 0; i < N; ++i) { dis[i] = inf; pre[i] = -1; vis[i] = false; } q.push(S); dis[S] = 0; vis[S] = true; pre[S] = -1; int u, v, w, i; while(!q.empty()) { u = q.front(); q.pop(); for(i = head[u]; i != -1; i = g[i].next) { v = g[i].to; w = g[i].cost; if(g[i].flow && dis[v] > dis[u] + w) { dis[v] = dis[u] + w; pre[v] = i; if(!vis[v]) { vis[v] = true; q.push(v); } } } vis[u] = false; } return dis[T] != inf; } int get_flow(int& Cost, int& Flow) { //增广路 int tmp = T; int res = inf; int c = 0; while(pre[tmp] != -1) { res = min(res, g[pre[tmp]].flow); tmp = g[pre[tmp]].from; } tmp = T; while(pre[tmp] != -1) { g[pre[tmp]].flow -= res; g[pre[tmp]^1].flow += res; c += g[pre[tmp]].cost*res; tmp = g[pre[tmp]].from; } //printf("%d %d\n", c, res); Cost += c; Flow += res; } char sst[N]; char dic[N][N]; int hh[50], ht[50]; int a[N], n, lent; int solve() { int Cost = 0, Flow = 0; //... while(spfa()) { get_flow(Cost, Flow); } //printf("%d %d\n", Flow, Cost); if(Flow == lent) return Cost; else return -1; } void build() { init(); S = 0; T = 127; lent = strlen(sst); int i, j; CL(hh, 0); for(i = 0; i < lent; ++i) { hh[sst[i]-'a' + 1]++; } for(i = 1; i <= 26; ++i) { if(hh[i]) { add(100 + i, T, hh[i], 0); //printf("%d -> %d %d %d\n", 100 + i, T, hh[i], 0); } } for(i = 1; i <= n; ++i) { add(S, i, a[i], 0); //printf("%d -> %d %d %d\n", S, i, a[i], 0); } for(i = 1; i <= n; ++i) { CL(ht, 0); for(j = 0; j < static_cast<int>(strlen(dic[i])); ++j) { ht[dic[i][j] - 'a' + 1] ++; } for(j = 1; j <= 26; ++j) { if(ht[j] && hh[j]) { add(i, 100 + j, ht[j], i); //printf("%d -> %d %d %d\n", i, 100 + j, ht[j], i); } } } } int main() { //Read(); scanf("%s", sst); scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%s %d", dic[i], &a[i]); } build(); printf("%d\n", solve()); return 0; }