【KM算法求最大权匹配】hdu 3722

来源:互联网 发布:桌面隐藏软件下载 编辑:程序博客网 时间:2024/06/05 06:58

貌似TLE了10来次吧。。。不记得改哪里咯,大概都是些初始化问题!

#include <list>#include <map>#include <set>#include <queue>#include <string>#include <deque>#include <stack>#include <algorithm>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <limits.h>#include <time.h>#include <string.h>using namespace std;#define LL long long#define PI acos(-1.0)#define Max INT_MAX#define Min INT_MIN#define eps 1e-8#define FRE freopen("a.txt","r",stdin)#define N 203//最大权匹配KM算法//int max(int a,int b){return a>b?a:b;}int w[N][N];bool vx[N],vy[N];int slack;int lx[N],ly[N];int mat[N];char str[203][1003];int  n;bool Path(int s){//找增广路    int tmp;    vx[s]=1;    int i,j;    for(i=0;i<n;i++){        if(vy[i])continue;        tmp=lx[s]+ly[i]-w[s][i];        if(tmp==0){            vy[i]=1;            if(mat[i]==-1 || Path(mat[i])){                mat[i]=s;                return true;            }        }        else        if(slack>tmp)        slack=tmp;    }    return false;}void KM(){    int i,j;    //(1)初始化可行顶标的值;    memset(ly,0,sizeof(ly));    memset(mat,-1,sizeof(mat));    for(i=0;i<n;i++){        lx[i]=Min;        for(j=0;j<n;j++){           if(lx[i]<w[i][j])lx[i]=w[i][j];        }    }    //(2)用匈牙利算法寻找完备匹配;    for(i=0;i<n;i++){        while(1){        for(j=0;j<=n;j++)        vx[j]=vy[j]=0;        slack=Max;        //(4)重复(2)(3)直到找到相等子图的完备匹配为止;        if(Path(i))break;        //(3)若未找到完备匹配则修改可行顶标的值;        for(j=0;j<n;j++){            if(vx[j])            lx[j]-=slack;            if(vy[j])            ly[j]+=slack;            }        }    }    int ans=0;    for(i=0;i<n;i++){        ans += w[mat[i]][i];    }    printf("%d\n",ans);}int main(){    while(scanf("%d",&n)!=EOF){        int i,j;        for(i=0;i<n;i++)        scanf("%s",str[i]);        memset(w,0,sizeof(w));//        for(i=0;i<n;i++){            for(j=0;j<n;j++){                if(i==j){continue;}                int s1=strlen(str[i])-1;                int s2=0;                int cnt=0;                int len=strlen(str[j]);                while(s1>=0 && s2<len){//求相同前缀!                    if(str[i][s1] == str[j][s2])                    {                        cnt++;                        s1--;                        s2++;                    }                    else                    break;                }                w[i][j]=cnt;            }        }        KM();    }    return 0;}


原创粉丝点击