HDU 3722 最大效益圈覆盖
来源:互联网 发布:mac玩国服lol 编辑:程序博客网 时间:2024/05/19 04:54
题意:给你n个字符串,任意两个字符串可以对接,假如字符串a接在字符串b的前面,则收益为a的后缀与b的前缀连续相同的字符的个数,同一个字符串自身也可以相接,但是收益为0。
分析:因为每个字符串自身可以相接,所以所有字符串接好后形成了一个或者若干个环,我们联想到二分图完备匹配,当二分图得到完备匹配时,肯定形成了若干个环,又因为有权值存在,所以我们想到用二分图最大权值完备匹配,直接上KM模板即可。
代码:
//其实在求最大 最小的时候只要用一个模板就行了,把边的权值去相反数即可得到另外一个.求结果的时候再去相反数即可//邻接矩阵特别需要注意重边的问题,切记#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll; //记得必要的时候改成无符号const int maxn=205;const int INF=1000000000;int n,nx,ny;int march[maxn],lx[maxn],ly[maxn],slack[maxn]; //lx,ly为顶标,nx,ny分别为x点集y点集的个数int w[maxn][maxn];bool visx[maxn],visy[maxn];int z[maxn];int dfs(int x){ visx[x]=1; for(int y=1;y<=ny;y++) { if(visy[y]) continue; int t=lx[x]+ly[y]-w[x][y]; if(t==0) { visy[y]=1; if(march[y]==-1||dfs(march[y])) { march[y]=x; return 1; } } else if(slack[y]>t) //不在相等子图中slack 取最小的 slack[y]=t; } return 0;}int KM(){ int i,j; memset(march,-1,sizeof(march)); memset(ly,0,sizeof(ly)); for(i=1;i<=nx;i++) //lx初始化为与它关联边中最大的 for(j=1,lx[i]=-INF;j<=ny;j++) if(w[i][j]>lx[i]) lx[i]=w[i][j]; for(int x=1;x<=nx;x++) { for(i=1;i<=ny;i++)slack[i]=INF; while(1) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(dfs(x)) //若成功(找到了增广轨),则该点增广完成,进入下一个点的增广 break; //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。 //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d, //所有在增广轨中的Y方点的标号全部加上一个常数d int d=INF; for(i=1;i<=ny;i++) if(!visy[i]&&d>slack[i]) d=slack[i]; for(i=1;i<=nx;i++) if(visx[i]) lx[i]-=d; for(i=1;i<=ny;i++) //修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d if(visy[i]) ly[i]+=d; else slack[i]-=d; } } int res=0; for(i=1;i<=ny;i++){ if(march[i]>-1){ res+=w[march[i]][i]; } } return res;}int js(char* s,char* t){ int x,y,k=0; x=strlen(s)-1; y=0; while(x>=0&&t[y]!='\0'){ if(s[x]==t[y]){ k++; x--; y++; } else break; } return k;}int main(){ int i,j,t; char s[205][1005]; while(~scanf("%d",&n)) { for(i=1;i<=n;i++){ scanf("%s",s[i]); } for(i=1;i<=n;i++){ for(j=i;j<=n;j++){ if(i==j){ w[i][j]=w[j][i]=0; continue; } t=js(s[i],s[j]); w[i][j]=t; t=js(s[j],s[i]); w[j][i]=t; } } nx=ny=n; printf("%d\n",KM()); } return 0;}
0 0
- HDU 3722 最大效益圈覆盖
- HDU 3488 最小费用圈覆盖
- hdu 1077 圆覆盖的最大点数
- 简单的背包最大效益问题
- hdu1853/ hdu 3488 有向图,取k个圈覆盖所有点一次//费用流
- HDU-1498(二分匹配_求最大覆盖定点数)
- hdu 1150 二分图 最小点覆盖=最大匹配
- hdu 1150 Machine Schedule 最小顶点覆盖(最大匹配)
- hdu 1151 Air Raid 最小路径覆盖(最大匹配)
- hdu 3360 National Treasures 最小顶点覆盖(最大匹配)
- hdu 1050 Moving Tables(最大区间覆盖问题)
- HDU 1528 (二分图最大匹配 + 最小覆盖, 14.07.17)
- hdu 1150 二分图最大匹配最小点覆盖
- HDU 4862 最小费用最大流+路径覆盖
- HDU 4883 TIANKENG’s restaurant (最大覆盖数)
- 二分图 最小覆盖数 = 最大匹配数、最大独立集 = 总数-最小覆盖集 证明 hdu 1068
- 发挥CRM最大效益的支点在哪
- hdoj 4322 Candy 【最大费用最大流】【经典题目】【最大流时 维护费用的最大效益】
- 职员有薪水了
- Python 二进制/十进制等转换
- POJ 1755 Triathlon(n^2 半平面交, 两点式和参数式直线求交点)
- java8中的Date、DateTime、Instant
- 【eclipse插件开发实战】Eclipse插件开发1——eclipse内核结构、扩展点机制
- HDU 3722 最大效益圈覆盖
- 简单判环
- Monkey and Banana - HDU 1069 dp
- 关于自适应屏幕方向和大小的一些经验
- Visual C++ 2012入门经典(第6版) 课后练习(第04章)
- 工作一年回忆录
- 功率和dB的关系
- hibernate4事务+Session管理
- java中关键字volatile的作用