题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=29821
思路:首先拆点,每个字符对应的位置拆成i和i+len,然后源点和i连边,容量为1,花费为0,i+len与汇点连边,容量为1,花费为0,然后就是对于那些在P中的字符串连边,容量为1,花费为g[u][v],最后跑最小费最大流即可,然后答案就是len-flow,cost;
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<climits> 6 #include<cstdlib> 7 #include<algorithm> 8 #include<stack> 9 #include<vector> 10 #include<queue> 11 #include<string> 12 #include<cmath> 13 #include<set> 14 using namespace std; 15 #define inf 1<<30 16 #define INF 1LL<<60 17 typedef long long ll; 18 typedef pair<int,int>PP; 19 #define MAXN 1111 20 21 struct Edge{ 22 int v,cap,cost,next; 23 }edge[MAXN*MAXN]; 24 25 int len,vs,vt,NE; 26 int head[MAXN]; 27 28 void Insert(int u,int v,int cap,int cost) 29 { 30 edge[NE].v=v; 31 edge[NE].cap=cap; 32 edge[NE].cost=cost; 33 edge[NE].next=head[u]; 34 head[u]=NE++; 35 36 edge[NE].v=u; 37 edge[NE].cap=0; 38 edge[NE].cost=-cost; 39 edge[NE].next=head[v]; 40 head[v]=NE++; 41 } 42 43 int pre[MAXN],cur[MAXN]; 44 bool mark[MAXN]; 45 int dist[MAXN]; 46 47 bool spfa(int vs,int vt) 48 { 49 memset(mark,false,sizeof(mark)); 50 fill(dist,dist+MAXN,inf); 51 dist[vs]=0; 52 queue<int>que; 53 que.push(vs); 54 while(!que.empty()){ 55 int u=que.front(); 56 que.pop(); 57 mark[u]=false; 58 for(int i=head[u];i!=-1;i=edge[i].next){ 59 int v=edge[i].v,cost=edge[i].cost; 60 if(edge[i].cap>0&&dist[u]+cost<dist[v]){ 61 dist[v]=dist[u]+cost; 62 pre[v]=u; 63 cur[v]=i; 64 if(!mark[v]){ 65 mark[v]=true; 66 que.push(v); 67 } 68 } 69 } 70 } 71 return dist[vt]<inf; 72 } 73 74 void MinCostFlow(int vs,int vt) 75 { 76 int flow=0,cost=0; 77 while(spfa(vs,vt)){ 78 int aug=inf; 79 for(int u=vt;u!=vs;u=pre[u]){ 80 aug=min(aug,edge[cur[u]].cap); 81 } 82 flow+=aug,cost+=dist[vt]*aug; 83 for(int u=vt;u!=vs;u=pre[u]){ 84 edge[cur[u]].cap-=aug; 85 edge[cur[u]^1].cap+=aug; 86 } 87 } 88 printf("%d %d\n",len-flow,cost); 89 } 90 91 92 char str1[MAXN],str2[MAXN]; 93 int g[MAXN][MAXN]; 94 int main() 95 { 96 int _case; 97 scanf("%d",&_case); 98 while(_case--){ 99 scanf("%s",str1); 100 len=strlen(str1); 101 memset(g,0,sizeof(g)); 102 for(int i=0;i<len-1;i++){ 103 int u=str1[i]-'a',v=str1[i+1]-'a'; 104 if(!g[u][v]){ 105 g[u][v]=(i+1)*(i+1); 106 } 107 } 108 scanf("%s",str2); 109 len=strlen(str2); 110 vs=0,vt=2*len+1; 111 NE=0; 112 memset(head,-1,sizeof(head)); 113 for(int i=0;i<len;i++){ 114 Insert(vs,i+1,1,0); 115 Insert(i+1+len,vt,1,0); 116 for(int j=i+1;j<len;j++){ 117 int u=str2[i]-'a',v=str2[j]-'a'; 118 if(g[u][v]){ 119 Insert(i+1,j+1+len,1,g[u][v]); 120 } 121 } 122 } 123 MinCostFlow(vs,vt); 124 } 125 return 0; 126 } 127 128 129 130 131