hdu 3722Card Game(KM匹配求环)

来源:互联网 发布:华侨大学hqu网络 编辑:程序博客网 时间:2024/05/19 01:30
//求图中环的最大权//直接拆点,求二分图的最大权匹配。#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define clr(a) memset(a,0,sizeof(a));const int N=300;const int INF=0x3fffffff;char dic[204][1024];int score[204][204];struct KM{    int lx[N],ly[N];//顶标    int visx[N],visy[N];    int line[N];    int we[N];//已配对所对应边权值    int nx,ny;    int slack;    bool find(int u){        visx[u]=true;        for(int v=1;v<=ny;v++){            if(!visy[v])//v不在相等子图中            {                int t=lx[u]+ly[v]-score[u][v];                if(t==0){                    visy[v]=1;                    if(line[v]==-1||find(line[v])){                        line[v]=u;                        we[v]=score[u][v];                        return 1;                    }                }                else if(t<slack)                    slack=t;                }            }        return 0;    }    bool km(){//返回是否完备匹配        clr(lx);clr(ly);        memset(line,-1,sizeof(line));        for(int i=1;i<=nx;i++){            for(int j=1;j<=ny;j++){                if(score[i][j]>lx[i])                    lx[i]=score[i][j];//初始化为xi所连接的最大权值            }        }        for(int u=1;u<=nx;u++)        {            while(true){                slack=INF;                clr(visx);clr(visy);                if(find(u))break;                if(slack==INF)return 0;                for(int i=1;i<=nx;i++){                    if(visx[i])lx[i]-=slack;                }                for(int i=1;i<=ny;i++){                    if(visy[i])ly[i]+=slack;                }            }        }        return 1;    }    int best_match(){        int res=0;        km();        for(int u=1;u<=ny;u++){            if(line[u]==-1)continue;            res+=we[u];        }        return res;    }}kk;int main(){    int n;    while(scanf("%d",&n)!=EOF){        for(int i=1;i<=n;i++){            scanf("%s",dic[i]);        }        clr(score);        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                if(i==j)continue;                int leni=strlen(dic[i]);                int lenj=strlen(dic[j]);                int k=0;                for(int l=0,r=leni-1;l<lenj&&r>=0;l++,r--){                    if(dic[i][r]==dic[j][l])k++;                    else break;                }                score[i][j]=k;            }        }        kk.nx=kk.ny=n;        printf("%d\n",kk.best_match());    }    return 0;}

0 0