zoukankan      html  css  js  c++  java
  • HDU3718 Similarity KM

    原文链接http://www.cnblogs.com/zhouzhendong/p/8284763.html


    题目传送门 - HDU3718


    题意概括

      直接描述输入吧

      首先一个T(T<15),表示数据组数。

      每组数据,首先三个数:len,k,m,分别表示接下来要读入的字符串的长度、每一个字符串中出现的不同字母个种类数、询问的字符串数。(len<=10000)(k<=26)(m<30)

      然后一行一个标准串。(长度为len)

      然后m行,每行一个询问串。(长度为len)

      对于询问串,每一种字母可以对应一种字母,问在最优方案下,使得对应万之后满足询问串与标准串的对应位相同的位的个数除以len的值。

      完(kou)美(hu)


    题解

      我想骂人。

      容我说点难听的话。

      这题的样例数据简直就是垃圾。

      第46行的j++写成了i++居然过了样例然后实测无限TLE?

      

      言归正传。

      我们考虑每一个字母变成另一个字母得到的贡献,然后在这两个字母之间连一条边,边权为贡献。

      然后貌似就是裸的KM了。

      OK水题。


    代码

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int INF=1e9+7;
    const int N=30,L=10005;
    int T,len,n,m,g[N][N];
    char cor[L],now[L];
    int ex[N],ey[N],minadd[N],match[N];
    bool visx[N],visy[N];
    bool Match(int x){
    	visx[x]=1;
    	for (int i=1;i<=n;i++)
    		if (!visy[i]){
    			int add=ex[x]+ey[i]-g[x][i];
    			if (!add){
    				visy[i]=1;
    				if (!match[i]||Match(match[i])){
    					match[i]=x;
    					return 1;
    				}
    			}
    			else
    				minadd[i]=min(minadd[i],add);
    		}
    	return 0;
    }
    int KM(){
    	memset(match,0,sizeof match);
    	memset(ex,0,sizeof ex);
    	memset(ey,0,sizeof ey);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			ex[i]=max(ex[i],g[i][j]);
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++)
    			minadd[j]=INF;
    		while (1){
    			memset(visx,0,sizeof visx);
    			memset(visy,0,sizeof visy);
    			if (Match(i))
    				break;
    			int d=INF;
    			for (int j=1;j<=n;j++)
    				if (!visy[j])
    					d=min(d,minadd[j]);
    			for (int j=1;j<=n;j++){
    				if (visx[j])
    					ex[j]-=d;
    				if (visy[j])
    					ey[j]+=d;
    				else
    					minadd[j]-=d;
    			}
    		}
    	}
    	int ans=0;
    	for (int i=1;i<=n;i++)
    		ans+=g[match[i]][i];
    	return ans;
    }
    void readstr(char s[]){
    	char ch[5];
    	for (int i=1;i<=len;i++){
    		scanf("%s",ch);
    		s[i]=ch[0];
    	}
    }
    int main(){
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d%d",&len,&n,&m);
    		n=26;
    		readstr(cor);
    		while (m--){
    			readstr(now);
    			memset(g,0,sizeof g);
    			for (int i=1;i<=len;i++)
    				g[now[i]-'A'+1][cor[i]-'A'+1]++;
    			printf("%.4lf
    ",1.0*KM()/len);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    (BFS 二叉树) leetcode 515. Find Largest Value in Each Tree Row
    (二叉树 BFS) leetcode513. Find Bottom Left Tree Value
    (二叉树 BFS DFS) leetcode 104. Maximum Depth of Binary Tree
    (二叉树 BFS DFS) leetcode 111. Minimum Depth of Binary Tree
    (BFS) leetcode 690. Employee Importance
    (BFS/DFS) leetcode 200. Number of Islands
    (最长回文子串 线性DP) 51nod 1088 最长回文子串
    (链表 importance) leetcode 2. Add Two Numbers
    (链表 set) leetcode 817. Linked List Components
    (链表 双指针) leetcode 142. Linked List Cycle II
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU3718.html
Copyright © 2011-2022 走看看