hdu3722Card Game(KM最大带权匹配)

来源:互联网 发布:知天下资源吧网址 编辑:程序博客网 时间:2024/05/16 03:09
 

hdu3722Card Game(KM最大带权匹配)

分类: 最大匹配 图论 198人阅读 评论(0) 收藏 举报
图论

题目请戳这里

题目大意:给n个字符串,再给一个n的排列:p1,p2....pn。然后将第i个字符串贴到第pi个字符串后面,然后形成一个环。pi的首字符和第i个字符串的末尾字符就相邻,如果这2个字符相等,各自再向内延伸一个位置,知道这个环首尾字符不等为止。延伸的位置为该环的得分(如果pi == i,得分为0),对于每个排列,有n个这样的环,求得分和最大为多少。

题目分析:最大带权匹配!!以为是个字符串的题目,就没仔细看。。。

建图直接跑模版。。。

详情请见代码:

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. using namespace std;  
  5. const int N = 205;  
  6. const int M = 1005;  
  7. const int inf = 0x3f3f3f3f;  
  8. char s[N][M];  
  9. int n;  
  10. int lx[N],ly[N],w[N][N];  
  11. bool cx[N],cy[N];  
  12. int match[N];  
  13. int slack;  
  14. int getw(int x,int y)  
  15. {  
  16.     int i,j;  
  17.     i = strlen(s[x]) - 1;  
  18.     j = 0;  
  19.     int lenj = strlen(s[y]) - 1;  
  20.     int ret = 0;  
  21.     while(i >= 0 && j <= lenj && s[x][i] == s[y][j])  
  22.         i --,j ++,ret ++;  
  23.     return ret;  
  24. }  
  25. void predeal()  
  26. {  
  27.     int i,j;  
  28.     for(i = 1;i <= n;i ++)  
  29.     {  
  30.         for(j = 1;j <= n;j ++)  
  31.             if(i == j)  
  32.                 w[i][j] = 0;  
  33.             else  
  34.                 w[i][j] = getw(i,j);  
  35.     }  
  36. }  
  37. bool path(int u)  
  38. {  
  39.     cx[u] = true;  
  40.     for(int v = 1;v <= n;v ++)  
  41.     {  
  42.         if(cy[v] == false)  
  43.         {  
  44.             int t = lx[u] + ly[v] - w[u][v];  
  45.             if(t)  
  46.             {  
  47.                 if(slack > t)  
  48.                     slack = t;  
  49.             }  
  50.             else  
  51.             {  
  52.                 cy[v] = true;  
  53.                 if(match[v] == -1 || path(match[v]))  
  54.                 {  
  55.                     match[v] = u;  
  56.                     return true;  
  57.                 }  
  58.             }  
  59.         }  
  60.     }  
  61.     return false;  
  62. }  
  63. void KM()  
  64. {  
  65.     int ans = 0;  
  66.     int i,j;  
  67.     for(i = 1;i <= n;i ++)  
  68.     {  
  69.         lx[i] = -inf;  
  70.         ly[i] = 0;  
  71.         for(j = 1;j <= n;j ++)  
  72.             if(lx[i] < w[i][j])  
  73.                 lx[i] = w[i][j];  
  74.     }  
  75.     memset(match,-1,sizeof(match));  
  76.     for(i = 1;i <= n;i ++)  
  77.     {  
  78.         while(1)  
  79.         {  
  80.             memset(cx,false,sizeof(cx));  
  81.             memset(cy,false,sizeof(cy));  
  82.             slack = inf;  
  83.             if(path(i))  
  84.                 break;  
  85.             for(j = 1;j <= n;j ++)  
  86.             {  
  87.                 if(cx[j])  
  88.                     lx[j] -= slack;  
  89.                 if(cy[j])  
  90.                     ly[j] += slack;  
  91.             }  
  92.         }  
  93.     }  
  94.     for(i = 1;i <= n;i ++)  
  95.         ans += w[match[i]][i];  
  96.     printf("%d\n",ans);  
  97. }  
  98. int main()  
  99. {  
  100.     while(scanf("%d",&n) != EOF)  
  101.     {  
  102.         for(int i = 1;i <= n;i ++)  
  103.             scanf("%s",s[i]);  
  104.         predeal();  
  105.         KM();  
  106.     }  
  107.     return 0;  
  108. }  
原创粉丝点击