hdu 3718 二分图最佳匹配 占坑待补
来源:互联网 发布:java switch 例子 编辑:程序博客网 时间:2024/05/20 17:07
题目:
Similarity
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2160 Accepted Submission(s): 868
But the LABEL of group doesn't make sense and the LABEL is just used to indicate different groups. So the representations {P,P,O,P,O,O,Q,Q,Q,Q} and {E,E,F,E,F,F,W,W,W,W} are equivalent to the original mapping sequence. However, the representations {A,A,A,A,B,B,C,C,C,C} and
{D,D,D,D,D,D,G,G,G,G} are not equivalent.
The pupils in class submit their mapping sequences and the teacher should read and grade the homework. The teacher grades the homework by calculating the maximum similarity between pupils' mapping sequences and the answer sequence. The definition of similarity is as follow.
Similarity(S, T) = sum(Si == Ti) / L
L = Length(S) = Length(T), i = 1, 2,... L,
where sum(Si == Ti) indicates the total number of equal labels in corresponding positions. The maximum similarity means the maximum similarities between S and all equivalent sequences of T, where S is the answer and fixed. Now given all sequences submitted by pupils and the answer sequence, you should calculate the sequences' maximum similarity.
210 3 3A A B A B B C C C CF F E F E E D D D DX X X Y Y Y Y Z Z ZS T R S T R S T R S3 2 2A B AC D CF F E
1.00000.70000.50001.00000.6667
需要先了解几个定义:
顶标:图的顶点的标号
完全二分图:是一种特殊的二分图,可以把图中的顶点分成两个集合,使得第一个集合中的所有顶点都与第二个集合中的所有顶点相连
二分图的完备匹配:不含未匹配点的匹配 即二分图中所有点都有边相连的匹配
最优匹配:所有匹配边的权和最大的匹配方案
对于二分图的每条边都有一个权(非负),要求一种完备匹配方案,使得所有匹配边的权和最大,记做最优完备匹配。(特殊的,当所有边的权为1时,就是最大完备匹配问题)
可行顶标:L是一个关于结点的函数,L(x)是顶点x对应的顶标值。可行顶标对于图中的每条边(x,y)都有L(x)+L(y)>=w(x,y)
相等子图:只包含L(x)+L(y)=w(x,y)的边的子图
定理:如果一个相等子图中包含完备匹配,那么这个匹配就是最优匹配
[KM算法的几种变形]
1. KM算法是求最大权完备匹配,如果要求最小权完备匹配怎么办?方法很简单,只需将所有的边权值取其相反数,求最大权完备匹配,匹配的值再取相反数即可。
2. KM算法的运行要求是必须存在一个完备匹配,如果求一个最大权匹配(不一定完备,可以有未匹配点)该如何办?依然很简单,把不存在的边权值赋为0。
3. KM算法求得的最大权匹配是边权值和最大,如果我想要边权之积最大,又怎样转化?还是不难办到,每条边权取自然对数,然后求最大和权匹配,求得的结果a再算出e^a就是最大积匹配。至于精度问题则没有更好的办法了。
参考资料:
http://cse.seu.edu.cn/PersonalPage/hxue/downloadTalk/download5/%E4%BA%8C%E5%88%86%E5%9B%BE%E7%9A%84%E5%8C%B9%E9%85%8D%E9%97%AE%E9%A2%98-%E5%AD%94%E5%AD%90%E6%98%8E%EF%BC%8C%E5%90%B4%E6%A5%9A%E6%98%8A%EF%BC%8C%E8%8B%8F%E8%B5%9B.pdf
http://cse.seu.edu.cn/PersonalPage/hxue/downloadTalk/download5/%E4%BA%8C%E5%88%86%E5%9B%BE%E7%9A%84%E6%9C%80%E4%BD%B3%E5%8C%B9%E9%85%8D%E9%97%AE%E9%A2%98-%E5%90%95%E5%A4%A9%E7%BF%8E.pdf
https://www.byvoid.com/zhs/blog/match-km
http://111qqz.com/2016/06/hdu-2255-%E5%A5%94%E5%B0%8F%E5%BA%B7%E8%B5%9A%E5%A4%A7%E9%92%B1-%E4%BA%8C%E5%88%86%E5%9B%BE%E6%9C%80%E4%BD%B3%E5%8C%B9%E9%85%8D%EF%BC%8Ckm%E7%AE%97%E6%B3%95%E6%A8%A1%E6%9D%BF%E9%A2%98%EF%BC%89/
本题建图方法:
代码:
不清楚原理的情况下写出的一份貌合神离的辣鸡代码
#include<bits/stdc++.h>using namespace std;const int INF=0x3f3f3f3f;const int N=30;int nx,ny;//两边点数int g[N][N];//图 下标从0开始int linker[N],lx[N],ly[N];//y中各点匹配状态,两边顶标int slack[N];bool visx[N],visy[N];int t,n,m,k;bool dfs(int x){ visx[x]=true; for(int y=0;y<ny;++y){ if(visy[y]) continue; int tmp=lx[x]+ly[y]-g[x][y]; if(tmp==0){ visy[y]=true; if(linker[y]==-1||dfs(linker[y])){ linker[y]=x; return true; } } else if(slack[y]>tmp) slack[y]=tmp; } return false;}int KM(){ memset(linker,-1,sizeof(linker)); memset(ly,0,sizeof(ly)); for(int i=0;i<nx;++i){ lx[i]=-INF;//////lx[i]=; for(int j=0;j<k;++j){ if(g[i][j]>lx[i]) lx[i]=g[i][j]; } } for(int x=0;x<nx;++x){ for(int i=0;i<ny;++i) slack[i]=INF;//// while(1){ memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(dfs(x)) break; int d=INF; for(int i=0;i<ny;++i){ if(!visy[i] && d>slack[i]) d=slack[i]; } for(int i=0;i<nx;++i){ if(visx[i]) lx[i]-=d; } for(int i=0;i<ny;++i){ if(visy[i]) ly[i]+=d; else slack[i]-=d; } } } int res=0; for(int i=0;i<ny;++i){ if(linker[i]!=-1) res+=g[linker[i]][i]; } return res;}int main(){//327MS2012K char c[3]; scanf("%d",&t); while(t--){ string s; scanf("%d%d%d",&n,&k,&m); for(int i=0;i<n;++i){ scanf("%1s",c); s+=c[0]; } //cout<<s<<endl; memset(g,0,sizeof(g)); for(int i=0;i<m;++i){ for(int j=0;j<n;++j){ scanf("%1s",c); g[s[j]-'A'][c[0]-'A']++; } nx=26; ny=26; int ans=KM(); //cout<<ans<<endl; printf("%.4f\n",1.0*ans/(n*1.0)); } } return 0;}
111qqz的代码:
#include<bits/stdc++.h>using namespace std;#define ms(a,x) memset(a,x,sizeof(a))const int inf = 0x3f3f3f3f;const int N=1E4+7;int n,k,m;char a[35][N];int w[35][35];map<char,int>mp1,mp2;int tot1,tot2;int lx[35],ly[35];bool visx[35],visy[35];int link[35];int slk[35];bool find( int u){ visx[u] = true; for ( int v = 1 ; v <= k ; v++){ if (visy[v]) continue; int tmp = lx[u] + ly[v] - w[u][v]; if (tmp==0){ visy[v] = true; if (link[v]==-1||find(link[v])){ link[v] = u; return true; } }else if (tmp<slk[v]) slk[v] = tmp; } return false;}int KM(){ ms(link,-1); ms(lx,0); ms(ly,0); for ( int i = 1 ; i <= tot2 ; i++)for ( int j = 1 ; j <= k ; j++) lx[i] = max(lx[i],w[i][j]); for ( int i = 1 ; i <= tot2 ; i++){ ms(slk,0x3f); while (1){ ms(visx,false); ms(visy,false); if (find(i)) break; int d = inf; for ( int j = 1 ;j <= k ; j++) if (!visy[j]&&slk[j]<d) d = slk[j]; for ( int j = 1 ; j <= tot2 ; j++) if (visx[j]) lx[j]-=d; for ( int j = 1; j <= k ; j++) if (visy[j]) ly[j]+=d; else slk[j]-=d; } } int res = 0 ; for ( int i = 1 ; i <= k ; i++)if (link[i]>-1) res += w[link[i]][i]; return res;}int main(){//218MS2032Kint T;cin>>T;while (T--){ ms(w,0); mp1.clear(); mp2.clear(); tot1 = 0 ; tot2 = 0 ; scanf("%d%d%d",&n,&k,&m); getchar(); for ( int i = 0 ; i <= m ; i++){ for ( int j = 1 ; j <= n ; j++) scanf(" %c",&a[i][j]); getchar(); } for ( int i = 1 ; i <= n ; i++) if (!mp1[a[0][i]]) mp1[a[0][i]]=++tot1; for ( int i = 1; i <= m ; i++){ms(w,0);tot2 = 0 ;mp2.clear();for ( int j = 1 ; j <= n ; j++) if (!mp2[a[i][j]]) mp2[a[i][j]] = ++tot2;for ( int j = 1; j <= n ; j++) { int u = mp1[a[0][j]]; int v = mp2[a[i][j]]; w[v][u]++;}int ret = KM();double ans;ans = ret*1.0/(n*1.0);printf("%.4f\n",ans); }} return 0;}
还是不能着急功近利 一步一步来 学得慢没关系,每个人基础不一样,智商不一样,学起来也是不一样的速度。关键是学扎实,理解清楚,才能以不变应万变
- hdu 3718 二分图最佳匹配 占坑待补
- HDU 2853 Assignment(最佳二分图匹配)
- 二分图最佳匹配
- hdu - 3488 - Tour(二分图最佳完美匹配)
- HDU 4862 Jump 二分图最佳匹配KM算法
- HDU 2255 奔小康赚大钱(最佳二分图匹配)
- HDU 1533 Going Home(最佳二分匹配)
- 二分图最佳匹配 入门
- 二分图最佳匹配 题目
- 二分图的最佳匹配
- 二分图最佳完美匹配
- 二分图最佳完美匹配
- hdu2255 二分图最佳匹配
- 二分图 最佳匹配 最大权匹配
- 2010成都站J题 ||hdu 3718 二分图的最佳匹配 =〉 最小费用最大流
- HDU 3718 Similarity(二分图最优匹配)
- KM算法 二分图的最佳匹配
- 二分图的最佳匹配(KM 算法)
- maven3.5+hadoop2.7.3统计米骑测试日志KPI指标(四)
- 创建爬虫----导航树
- git相关操作
- 进程——孤儿进程与僵尸进程
- Linux调整LVM容量
- hdu 3718 二分图最佳匹配 占坑待补
- 查询与增改删功能
- ScriptManager的几个属性和方法
- Postman使用
- JSch 指令不识别
- Spring源码学习
- C++中成员变量加上static或const关键字后的分析
- python的虚拟环境应用
- Java中异常的抛出原则