首页 > 其他分享 >CF 237E(字母选取-费用流)

CF 237E(字母选取-费用流)

时间:2022-10-25 12:09:51浏览次数:60  
标签:pre map int 237E CF 选取 cost MAXN now


题目大意:有一字符串S,你需要从n个字符串中选取一些来拼出这个串,第i个字符串代价为i,限制取P次,问最小代价(无解输出-1)


建立超源S=0,超汇T=n+26+1 

1-n的结点为字符串 n+1-n+26的结点为字符

则可得——————————————————

从S向字符串连(最多可取数量),费用为i

从字符向T连(欲取数量)

从字符串向字符连(字符串可取该字母的数量)

得到图

跑费用……


!负数的布尔值为1.


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<algorithm>
#include<functional>
#include<iostream>
using namespace std;
#define MAXN (200+10)
#define M26 100
#define A 96
#define NONE (2139062143)
int map[MAXN][MAXN]={0},cost[MAXN][MAXN]={0},stf[M26]={0};
int start=0,end,n;
char s[5000];

int d[MAXN],pre[MAXN],q[MAXN*8];
bool b[MAXN];
void spfa()
{
memset(b,0,sizeof(b));
memset(d,127,sizeof(d));
memset(q,0,sizeof(q));
memset(pre,0,sizeof(pre));

int head=1,tail=1;
q[1]=start;b[start]=1;d[start]=0;
while (head<=tail)
{
int now=q[head];
for (int i=0;i<=end;i++)
if (map[now][i]>0&&d[now]+cost[now][i]<d[i])
{
d[i]=d[now]+cost[now][i];
pre[i]=now;
if (!b[i])
{
q[++tail]=i;
b[i]=1;
}

}

b[now]=0;
head++;
}



}
void hllp()
{
int totalcost=0;
while (1)
{
spfa();
if (d[end]==NONE) break;
int flow=NONE,i=end;
do
{
flow=min(flow,map[pre[i]][i]);
i=pre[i];
}while (i!=start);
i=end;
do
{
totalcost+=flow*cost[pre[i]][i];
map[pre[i]][i]-=flow;
map[i][pre[i]]+=flow;
i=pre[i];
}while (i!=start);

}
for (int i=end-27;i<end;i++)
if (map[i][end])
{
cout<<"-1\n";
return;

}
cout<<totalcost<<endl;
}



int main()
{
// freopen("c.in","r",stdin);
scanf("%s",s);
scanf("%d",&n);
int len=strlen(s);
for (int i=0;i<len;i++) stf[s[i]-A]++;
end=n+27;
for (int i=1;i<=26;i++) map[n+i][end]=stf[i];
for (int i=1;i<=n;i++)
{
scanf("%s",s);
scanf("%d",&map[start][i]);
memset(stf,0,sizeof(stf));
for (int j=0;j<strlen(s);j++) stf[s[j]-A]++;
for (int j=1;j<=26;j++) map[i][n+j]=stf[j];
cost[0][i]=i;
cost[i][0]=-cost[0][i];
}
/* for (int i=0;i<=end;i++)
for (int j=0;j<=end;j++)
if (map[i][j]) cout<<i<<' '<<j<<' '<<map[i][j]<<endl;
*/ hllp();
cout<<'\n';
/* for (int i=0;i<=end;i++)
for (int j=0;j<=end;j++)
if (map[i][j]) cout<<i<<' '<<j<<' '<<map[i][j]<<endl;
*/
return 0;
}



标签:pre,map,int,237E,CF,选取,cost,MAXN,now
From: https://blog.51cto.com/u_15724837/5794391

相关文章

  • CF1239E Turtle
    CF1239ETurtle给定\(2\timesn\)的棋盘,要求重新安排布局,使得所有从\((1,1)\)走到\((2,n)\)的路径中最大点权和最小。\(n\leq25,a_i\leq5\times10^4\)。首先确......
  • CF1523F Favorite Game
    CF1523FFavoriteGame给定\(n\)个传送门和\(m\)个地点。传送门需要提前前往才能打开,你可以不用任何时间传送到任何一个传送门,你可以步行\(1\)个单位\(1\)秒。每......
  • CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
    CF741DArpa’sletter-markedtreeandMehrdad’sDokhtar-koshpaths给定一颗以\(1\)为根的树每个节点上有一个\(a\simv\)的小写字母,求每个子树内最长的链的长度......
  • CF838B Diverging Directions
    题目链接:​​传送门​​分析一下他给的这个图就知道一个祖先到它的儿子只有生成树的边可以走而一个儿子走到祖先有两种方法一个是先直接到1,再从1走到那个祖先还有一个很......
  • CF1732D2 Balance (Hard version) 题解
    前天打了波CF结果怒掉100分,果然退化得太厉害了,遂于昨晚补题.题面维护一个集合SS,有三种操作:插入一个数、删除一个数、查询kk的倍数中没出现过的最小的数。思路考......
  • CF 253B(队列上维护2个指针后移)
    B.实验误差timelimitpertestmemorylimitpertestinputoutput小明做实验......
  • CF 254C(易位构字法)
    C.易位构字法timelimitpertestmemorylimitpertestinputoutput异位构字......
  • CF 254A(重复的数)
    A.数字卡片timelimitpertestmemorylimitpertestinputoutput2n张卡片编......
  • CF 254B(日期)
    B.评委会timelimitpertestmemorylimitpertestinputoutputn 场比赛,编号......
  • CF 254E(从当前向后递推)
    E.宿舍分享timelimitpertestmemorylimitpertestinputoutputn 天.第i天......