codeforces 717 G. Underfail(费用流,好题)
来源:互联网 发布:红五图库永久域名三毛 编辑:程序博客网 时间:2024/05/16 16:20
You have recently fallen through a hole and, after several hours of unconsciousness, have realized you are in an underground city. On one of your regular, daily walks through the unknown, you have encountered two unusually looking skeletons called Sanz and P’pairus, who decided to accompany you and give you some puzzles for seemingly unknown reasons.
One day, Sanz has created a crossword for you. Not any kind of crossword, but a 1D crossword! You are given m words and a string of length n. You are also given an array p, which designates how much each word is worth — the i-th word is worth pi points. Whenever you find one of the m words in the string, you are given the corresponding number of points. Each position in the crossword can be used at most x times. A certain word can be counted at different places, but you cannot count the same appearance of a word multiple times. If a word is a substring of another word, you can count them both (presuming you haven’t used the positions more than x times).
In order to solve the puzzle, you need to tell Sanz what’s the maximum achievable number of points in the crossword. There is no need to cover all postions, just get the maximal score! Crossword and words contain only lowercase English letters.
The first line of the input contains a single integer n (1 ≤ n ≤ 500) — the length of the crossword. The second line contains the crossword string. The third line contains a single integer m (1 ≤ m ≤ 100) — the number of given words, and next m lines contain description of words: each line will have a string representing a non-empty word (its length doesn't exceed the length of the crossword) and integer pi(0 ≤ pi ≤ 100). Last line of the input will contain x (1 ≤ x ≤ 100) — maximum number of times a position in crossword can be used.
Output single integer — maximum number of points you can get.
6abacba2aba 6ba 33
12
For example, with the string "abacba", words "aba" (6 points) and "ba" (3 points), and x = 3, you can get at most 12 points - the word "aba" appears once ("abacba"), while "ba" appears two times ("abacba"). Note that for x = 1, you could get at most 9 points, since you wouldn’t be able to count both "aba" and the first appearance of "ba".
题意:
说给一个主串和几个有价值的模式串,某个模式串与主串匹配就能累加对应的价值,一个模式串可以在多个位置和主串匹配但同一个位置只能一次,此外主串各个字符最多可以用x次,问如何匹配使获得的价值最大。
可以暴力得到每个模式串在主串中能够匹配时的起始位置和终点位置(也可以用AC自动机),然后是区间覆盖问题了,和这个题一样。
不过要注意,假如一个覆盖的区间为[l,r],那么加边是应该是[l,r+1),不然比如[1,1]这个区间建图就会出现负环了(求费用时有spfa过程)
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<queue>#include<stack>using namespace std;#define rep(i,a,n) for (int i=a;i<n;i++)#define per(i,a,n) for (int i=n-1;i>=a;i--)#define pb push_back#define fi first#define se secondtypedef vector<int> VI;typedef long long ll;typedef pair<int,int> PII;const ll mod=1e9+7;const int maxn=500+10;char s[maxn],s1[110];const int MAXM = maxn*maxn;const int INF = 0x3f3f3f3f;struct Edge{ int to,next,cap,flow,cost;}edge[MAXM];int head[maxn],tol;int pre[maxn],dis[maxn];bool vis[maxn];int N;//节点总个数,节点编号从0~N-1void init(int n){ N = n; tol = 0; memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,int cost){ edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}bool spfa(int s,int t){ queue<int> q; for(int i = 0;i < N;i++) { dis[i] = INF; vis[i] = false; pre[i] = -1; } dis[s] = 0; vis[s] = true; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i = head[u]; i != -1;i = edge[i].next) { int v = edge[i].to; if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]) { vis[v] = true; q.push(v); } } } } if(pre[t] == -1)return false; else return true;}//返回的是最大流,cost存的是最小费用int minCostMaxflow(int s,int t,int &cost){ int flow = 0; cost = 0; while(spfa(s,t)) { int Min = INF; for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) { if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; } return flow;}int main(){ int n; scanf("%d",&n); scanf("%s",s+1); int l=strlen(s+1); init(l+2); int m; scanf("%d",&m); rep(i,1,m+1) { scanf("%s",s1+1); int v; scanf("%d",&v); int l1=strlen(s1+1); for(int i=1;i<=l-l1+1;i++) { bool f=true; for(int j=1;j<=l1;j++) if(s[i+j-1]!=s1[j]) { f=false; break; } if(f) addedge(i,i+l1,1,-v); } } // cout << tol << endl; rep(i,1,l) addedge(i,i+1,INF,0); //cout << tol << endl; int x; scanf("%d",&x); addedge(0,1,x,0),addedge(l,l+1,INF,0); int ans=0; minCostMaxflow(0,l+1,ans); printf("%d\n",-ans); return 0;}
- codeforces 717 G. Underfail(费用流,好题)
- 【费用流】[CodeForces - 717G]Underfail
- [Underfail][CodeForces.717.G][费用流]
- [无源汇最大费用可行流 差分费用流] Codeforces 717G Bubble Cup 9 - Finals G. Underfail
- Codeforces 362 E Petya and Pipes【费用流】好题
- codeforces 863F Almost Permutation 费用流 好题!
- CodeForces - 659G Fence Divercity (DP)好题
- Codeforces 164C 费用流
- codeforces 730I (费用流)
- poj 2135 Farm Tour(最小费用最大流,好题)
- poj3686 The Windy's(拆点,费用流,好题)
- hdu 4862 Jump 【最小费用最大流】好题
- codeforces 277E 最小费用最大流
- Codeforces 237E Build String 【费用流】
- Codeforces 好题
- hdu 5988 Coding Contest 青岛G题 费用流以及一些感想吧
- HDU 5988 Coding Contest 2016青岛G题浮点费用流
- HDU 3315 My Brute 费用流+求错位率(好题)
- GS 稳定匹配算法 Java实现
- 安卓界面高级组件-----拖动条和评星条
- Dom
- pure-ftpd 搭建自己的FTP服务器
- 安装WAS8随记
- codeforces 717 G. Underfail(费用流,好题)
- OpenCV 及 OpenCV Samples 在 Window, Linux上的编译及使用
- DOM对象—节点的详解(一)
- 十:Java语言基础组成——函数
- preparedStatement.execute【犯傻心得】
- 程序设计基础-c#和java的区别
- SSH 相关
- 再读《learn less,study more》
- ElasticSearch 安装教程