zoukankan      html  css  js  c++  java
  • hdu 3722 Card Game 夜

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

    KM  先求出任意两个字符串前后匹配的值 然后KM求最大匹配

    越来越发现 图论题的关键在于建图呀

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<queue>
    #include<map>
    #include<string>
    #include <iomanip>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int N=205;
    const int M=1005;
    char stmp[N][M];
    int L[N];
    int dist[N][N];
    int f[N];
    bool lv[N],rv[N];
    int a[N],b[N];
    bool dfs(int x,int n)
    {
        lv[x]=true;
        for(int i=1;i<=n;++i)
        {
            if(!rv[i]&&a[x]+b[i]==dist[x][i])
            {
                rv[i]=true;
                if(f[i]==-1||dfs(f[i],n))
                {
                    f[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int Km(int n)
    {
        memset(f,-1,sizeof(f));
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;++i)
        {
            a[i]=-1;
            for(int j=1;j<=n;++j)
            a[i]=max(a[i],dist[i][j]);
        }
        for(int l=1;l<=n;++l)
        {
            while(true)
            {
                memset(lv,false,sizeof(lv));
                memset(rv,false,sizeof(rv));
                if(dfs(l,n))
                break;
                int d=INF;
                for(int i=1;i<=n;++i)
                {
                    if(lv[i])
                    for(int j=1;j<=n;++j)
                    {
                        if(!rv[j])
                        d=min(d,a[i]+b[j]-dist[i][j]);
                    }
                }
                for(int i=1;i<=n;++i)
                {
                    if(lv[i])
                    a[i]-=d;
                    if(rv[i])
                    b[i]+=d;
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;++i)
        {
            if(f[i]!=-1)
            ans+=dist[f[i]][i];
        }
        return ans;
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            getchar();
            for(int i=1;i<=n;++i)
            {gets(stmp[i]);L[i]=strlen(stmp[i]);}
            memset(dist,0,sizeof(dist));
            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<=n;++j)
                {
                    if(i==j)
                    continue;
                    int l1=L[i]-1;
                    int l2=0;
                    for(;l1>=0&&l2<L[j];--l1,++l2)
                    {
                        if(stmp[i][l1]!=stmp[j][l2])
                        break;
                    }
                    dist[i][j]=l2;
                }
            }
            printf("%d\n",Km(n));
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    DP 免费馅饼 HDU1176
    知了课堂 Python Flask零基础 笔记整理
    Splay入门
    字典树
    榨取kkksc03 多维dp
    种族并查集总结
    倍增总结
    求最大公因数(辗转相除法&更相减损术)
    Bzoj 3036: 绿豆蛙的归宿(期望)
    Bzoj 1497: [NOI2006]最大获利(最小割)
  • 原文地址:https://www.cnblogs.com/liulangye/p/2746626.html
Copyright © 2011-2022 走看看