Build String(CF-237E)
Problem Description
You desperately need to build some string t. For that you've got n more strings s1,?s2,?...,?sn. To build string t, you are allowed to perform exactly |t| (|t| is the length of string t) operations on these strings. Each operation looks like that:
- choose any non-empty string from strings s1,?s2,?...,?sn;
- choose an arbitrary character from the chosen string and write it on a piece of paper;
- remove the chosen character from the chosen string.
Note that after you perform the described operation, the total number of characters in strings s1,?s2,?...,?sn decreases by 1. We are assumed to build string t, if the characters, written on the piece of paper, in the order of performed operations form string t.
There are other limitations, though. For each string si you know number ai — the maximum number of characters you are allowed to delete from string si. You also know that each operation that results in deleting a character from string si, costs i rubles. That is, an operation on string s1 is the cheapest (it costs 1 ruble), and the operation on string sn is the most expensive one (it costs n rubles).
Your task is to count the minimum amount of money (in rubles) you will need to build string t by the given rules. Consider the cost of building string t to be the sum of prices of the operations you use.
Input
The first line of the input contains string t — the string that you need to build.
The second line contains a single integer n (1?≤?n?≤?100) — the number of strings to which you are allowed to apply the described operation. Each of the next n lines contains a string and an integer. The i-th line contains space-separated string si and integer ai (0?≤?ai?≤?100). Number ai represents the maximum number of characters that can be deleted from string si.
All strings in the input only consist of lowercase English letters. All strings are non-empty. The lengths of all strings do not exceed 100 characters.
Output
Print a single number — the minimum money (in rubles) you need in order to build string t. If there is no solution, print -1.
Examples
Input
bbaze
3
bzb 2
aeb 3
ba 10
Output
8
Input
abacaba
4
aba 2
bcc 1
caa 2
bbb 5
Output
18
Input
xyz
4
axx 8
za 1
efg 4
t 1
Output
-1
題意:給出一個字符串 str,然后有 n 個可供使用的字符串,現在在 n 個可用字符串中選取一定的字符組成字符串 str,從第 i 個串中拿一個字符的代價是 i 且最多拿 num[i] 個,求組成目標字符串的最小花費
思路:最小費用流
設置一個超級源點與超級匯點,從源點到 26 個字符建邊,容量記為字符串 str 的個數,費用為 0,然后將每個字符向 n 個字符串建邊,對于第 i 個串來說,容量為該串中相應字符的個數,費用為 i,最后對每個模式串向匯點建邊,容量為 num[i],費用為 0
最后如果出現滿流,則說明可以構造出 str 串
Source Program
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<bitset> #define EPS 1e-9 #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long const int MOD = 1E9+7; const int N = 10000+5; const int dx[] = {-1,1,0,0,-1,-1,1,1}; const int dy[] = {0,0,-1,1,-1,1,-1,1}; using namespace std;struct Edge{int from,to;int cap,flow;int cost;int next; }edge[N]; int head[N],tot; char str[N]; int bucket[27];//str串中字符個數 int G[N][27];//n個字符串每串的字符個數 int num[N];//n個字符串每串最多取的個數 int pre[N];//記錄從S到i的最小費用路徑上的最后一條弧編號 int dis[N]; bool vis[N]; bool SPFA(int S,int T) {queue<int> Q;memset(dis,INF,sizeof(dis));memset(vis,false,sizeof(vis));memset(pre,-1,sizeof(pre));dis[S]=0;Q.push(S);while(!Q.empty()) {int x=Q.front();Q.pop();vis[x]=false;for(int i=head[x];i!=-1;i=edge[i].next) {int y=edge[i].to;int cost=edge[i].cost;int cap=edge[i].cap;int flow=edge[i].flow;if(dis[y]>dis[x]+cost&&cap>flow) {dis[y]=dis[x]+cost;pre[y]=i;if(!vis[y]){vis[y]=true;Q.push(y);}}}}return pre[T]!=-1; } void MCMF(int S,int T,int &flow,int &cost){flow=0;cost=0;while(SPFA(S,T)){//每次尋找花銷最小的路徑int minn=INF;for(int i=pre[T];i!=-1;i=pre[edge[i^1].to])//尋找最小增廣流minn=min(minn,edge[i].cap-edge[i].flow);for(int i=pre[T];i!=-1;i=pre[edge[i^1].to]) {edge[i].flow+=minn;edge[i^1].flow-=minn;cost+=edge[i].cost*minn;//增廣流的花銷}flow+=minn;//總流量增加} }void addEdge(int from,int to,int cap,int flow,int cost){edge[tot].from=from;edge[tot].to=to;edge[tot].cap=cap;edge[tot].flow=flow;edge[tot].cost=cost;edge[tot].next=head[from];head[from]=tot++; }int main(){scanf("%s",str);int len=strlen(str);for(int i=0;i<len;i++)//統計str串中字符的個數bucket[str[i]-'a'+1]++;int n;scanf("%d",&n);for(int i=1;i<=n;i++){char temp[N];scanf("%s%d",temp,&num[i]);int length=strlen(temp);for(int j=0;j<length;j++)G[i][temp[j]-'a'+1]++;//統計第i個字符串中字符的個數}tot=0;memset(head,-1,sizeof(head));int S=0,T=26+n+1;for(int i=1;i<=26;i++){if(bucket[i]==0)continue;//源點到26個字符addEdge(S,i,bucket[i],0,0);//正向邊addEdge(i,S,0,0,0);//反向邊for(int j=1;j<=n;j++){if(G[j][i]==0)continue;//26個字符到n個字符串addEdge(i,26+j,G[j][i],0,j);//正向邊addEdge(26+j,i,0,0,-j);//反向邊}}for(int i=1;i<=n;i++){//n個字符串到匯點addEdge(26+i,T,num[i],0,0);//正向邊addEdge(T,26+i,0,0,0);//反向邊}int flow,cost;MCMF(S,T,flow,cost);if(flow!=len)//不滿流printf("-1\n");else//滿流printf("%d\n",cost);return 0; }?
總結
以上是生活随笔為你收集整理的Build String(CF-237E)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串处理 —— AC 自动机
- 下一篇: 计算几何 —— 二维几何基础 —— 三角