码迷,mamicode.com
首页 > 编程语言 > 详细

HDU 3722 Card Game(二分图最佳完美匹配+KM算法)

时间:2018-05-18 00:30:46      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:for   can   color   eof   date()   max   printf   target   names   

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3722

  1 /*
  2 问题 
  3 将任意的两个字符串进行匹配,使得匹配后权值和最大
  4 
  5 解题思路
  6 将任意的字符串的权值计算出来,使用KM算法即可。 
  7 */ 
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<algorithm>
 11 using namespace std;
 12 
 13 const int maxn=210;
 14 int W[maxn][maxn],n;
 15 char s[maxn][1100];
 16 int lx[maxn],ly[maxn];
 17 int left[maxn];
 18 bool S[maxn],T[maxn];
 19 int len[maxn];
 20 
 21 void presolve();
 22 int KM();
 23 bool match(int i);
 24 void update();
 25 
 26 int main()
 27 {
 28     int i,j;
 29     while(scanf("%d",&n) != EOF)
 30     {
 31         for(i=1;i<=n;i++)
 32         {
 33             scanf("%s",s[i]);
 34             len[i]=strlen(s[i]);
 35         }
 36         presolve();
 37 
 38         printf("%d\n",KM());
 39     }
 40 }
 41 
 42 bool match(int i)
 43 {
 44     S[i]=true;
 45     for(int j=1;j<=n;j++) if(lx[i]+ly[j] == W[i][j] && !T[j]){
 46         T[j]=true;
 47         if(!left[j] || match(left[j])){
 48             left[j]=i;
 49             return true;
 50         }
 51     }
 52     return false;
 53 }
 54 
 55 void update()
 56 {
 57     int a= 1<<30;
 58     for(int i=1; i<=n; i++){
 59         if(S[i]){
 60             for(int j=1;j<=n;j++){
 61                 if(!T[j]){
 62                     a = min(a,lx[i]+ly[j] - W[i][j]);
 63                 }
 64             }
 65         }
 66     }
 67     
 68     for(int i=1;i<=n;i++){
 69         if(S[i])    lx[i] -= a;
 70         if(T[i])    ly[i] += a;
 71     }
 72 }
 73 
 74 int KM()
 75 {
 76     for(int i=1;i<=n;i++){
 77         left[i] = lx[i] = ly[i] = 0;
 78         for(int j=1; j<=n; j++)
 79             lx[i]=max(lx[i],W[i][j]);    
 80     }
 81     
 82     for(int i=1; i<=n; i++){
 83         for(;;){
 84             for(int j=1;j<=n;j++){
 85                 S[j]=T[j]=0;
 86             }
 87             if(match(i)) break;
 88             else update();
 89         }
 90     }
 91     
 92     int ans=0;
 93     for(int i=1;i<=n;i++)
 94         ans += W[left[i]][i];
 95     return ans;
 96 }
 97 
 98 void presolve()
 99 {
100     int i,j,k,p1,p2,cnt;
101     for(i=1;i<=n;i++)
102     {
103         for(j=1;j<=n;j++)
104         {
105             if(i==j)
106             {
107                 W[i][j]=0;
108                 continue ;
109             }
110             
111             cnt=0;
112             p1=len[i]-1;
113             p2=0;
114             while(1)
115             {
116                 if(s[i][p1]==s[j][p2]) cnt++;
117                 else break ;
118                 p1--,p2++;
119                 if(p1<0 || p2>=len[j]) break ;
120             }
121             W[i][j]=cnt;
122         }
123     }
124 }

 

HDU 3722 Card Game(二分图最佳完美匹配+KM算法)

标签:for   can   color   eof   date()   max   printf   target   names   

原文地址:https://www.cnblogs.com/wenzhixin/p/9053758.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!