HDU 3395 Special Fish KM算法+邻接矩阵建图

题意:一个点可以连一些点,但每个点这能被用一次,权值是两点权值的异或,求匹配权值最大。


想法:简单的KM,但是用前向星就超时,郁闷啊!


#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 1<<30
using namespace std;
const int nodes=101;
const int edges=10000+50;
int n,val[nodes];
int map[nodes][nodes];
int link[nodes],linkx[nodes],visx[nodes],visy[nodes],slack[nodes],x[nodes],y[nodes];
int dfs(int u)
{
    visx[u]=1;
    for(int i=1;i<=n;i++)
    {
        int v=i;
        if(visy[v]) continue;
        int fu=x[u]+y[v]-map[u][v];
        if(!fu)
        {
            visy[v]=1;
            if(link[v]==-1||dfs(link[v]))
            {
            	linkx[u]=v;
                link[v]=u;
                return 1;
            }
        }
        else if(fu<slack[v])
        slack[v]=fu;
    }
    return 0;
}
int Max(int a,int b)
{
    if(a>b) return a;
    return b;
}
int KM()
{
    for(int i=1;i<=n;i++)
    {
        x[i]=-inf;
        for(int j=1;j<=n;j++)
        {
            x[i]=Max(x[i],map[i][j]);
        }
    }
    memset(y,0,sizeof(y));
    memset(link,-1,sizeof(link));
    memset(linkx,-1,sizeof(linkx));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        slack[j]=inf;
        while(1)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(dfs(i)) break;
            int tmp=inf;
            for(int j=1;j<=n;j++)
            {
                if(!visy[j]&&tmp>slack[j])
                {
                    tmp=slack[j];
                }
            }
            for(int j=1;j<=n;j++)
            {
                if(visx[j]) x[j]-=tmp;
            }
            for(int j=1;j<=n;j++)
            {
                if(visy[j]) y[j]+=tmp;
                else slack[j]-=tmp;
            }
        }
    }
    int res=0;
    for(int i=1;i<=n;i++)
    {
    	if(linkx[i]!=-1)
        res+=map[i][linkx[i]];
    } 
    return res;
}

int main()
{
	while(~scanf("%d",&n),n)
	{
		memset(map,0,sizeof(map));
		for(int i=1;i<=n;i++)
		scanf("%d",&val[i]);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				char c;
				cin>>c;
				if(c=='1')
				{
					map[i][j]=val[i]^val[j];
				}
			}
		}
		int res=KM();
		printf("%d\n",res);
	}
	return 0;
} 

你可能感兴趣的:(HDU 3395 Special Fish KM算法+邻接矩阵建图)