hdu2813one fight one

明顯的二分圖的最佳匹配,直接用map+最小費用最大流,但是很悲慘的超時了,後來換成字典樹+最小費用最大流,還是超時,哪位能幫我看一下哪有問題嗎?在網上搜了一下,這個題大家都是用KM算法做的,難道最小費用最大流不可以???

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int oo=1e7;
const int mm=111111;
const int mn=8888;
int node,src,dest,edge;
int ver[mm],flow[mm],cost[mm],next[mm];
int head[mn],dis[mn],p[mn],q[mn],vis[mn],work[mn];
void prepare(int _node,int _src,int _dest)
{
   node=_node,src=_src,dest=_dest;
   for(int i=0;i<node;++i)head[i]=-1,vis[i]=0;
   edge=0;
}
void addedge(int u,int v,int f,int c)
{
   ver[edge]=v,flow[edge]=f,cost[edge]=c,next[edge]=head[u],head[u]=edge++;
   ver[edge]=u,flow[edge]=0,cost[edge]=-c,next[edge]=head[v],head[v]=edge++;
}
bool spfa()
{
    int i,u,v,l,r=0,tmp;
    for(i=0;i<node;i++) dis[i]=oo;
    dis[q[r++]=src]=0;
    p[src]=p[dest]=-1;
    for(l=0;l!=r;(++l>=mn)?l=0:l)
        for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i])
            if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
            {
                dis[v]=tmp;//cout<<"u="<<u<<" v="<<v<<" tmp="<<tmp<<endl;
                p[v]=i^1;
                if(vis[v])  continue;
                vis[q[r++]=v]=1;
                if(r>=mn)   r=0;
            }
    return p[dest]>-1;
}
int Spfaflow()
{
    int i,ret=0,delta;
    while(spfa())
    {
        for(i=p[dest],delta=oo;i>=0;i=p[ver[i]])
            if(flow[i^1]<delta) delta=flow[i^1];
        for(i=p[dest];i>=0;i=p[ver[i]])
            flow[i]+=delta,flow[i^1]-=delta;
        ret+=delta*dis[dest];//cout<<"ret="<<ret<<endl;
    }
    return ret;
}
int nodecnt;
int root;
struct Dic
{
	int next[256];
	int k;
};
Dic nod[10000];
int NewNode()
{
	memset(nod[nodecnt].next, -1, sizeof(int)* 256);
	nod[nodecnt].k = -1;
	return nodecnt++;
}
int dic_insert(char * s, int &cnt)
{
	int i;
	int x = root;
	for (i = 0; s[i]; i++)
	{
		if (nod[x].next[s[i]] == -1)
		{
			nod[x].next[s[i]] = NewNode();
		}
		x = nod[x].next[s[i]];
	}
	if (nod[x].k == -1)
	{
		nod[x].k = cnt++;
	}
	return nod[x].k;
}
int main()
{
    int n,m,k,ans,i,j,cc,num1,num2;
    char a[23],b[23];
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        prepare(2+m+n,0,n+m+1);
        nodecnt = 0;
		root = NewNode();
		int acnt = 0;
		int bcnt = 0;
        while(k--)
        {
            scanf("%s %s %d",a,b,&cc);
            num1=dic_insert(a,acnt);num1++;
            num2=dic_insert(b,bcnt);num2++;
            //cout<<"num1="<<num1<<" num2="<<num2<<endl;
            addedge(num1,num2+n,oo,cc);
        }
        for(i=1;i<=n;i++)
            addedge(src,i,1,0);
        for(i=1;i<=m;i++)
            addedge(i+n,dest,1,0);
        printf("%d\n",Spfaflow());
    }
    return 0;
}

下面的是KM+字典樹

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<stack>
#include<bitset>
#include<queue>
#include<iostream>

using namespace std;

const int MaxN = 205;
const int oo = 0x7f7f7f7f;

int w[MaxN][MaxN];
int lx[MaxN];
int ly[MaxN];
int linky[MaxN];
int visx[MaxN];
int visy[MaxN];
int slack;
int N;
int M;
bool find(int x)
{
	visx[x] = true;
	int y;
	for (y = 0; y < M; y++)
	{
		if (visy[y] || w[x][y] == oo)
		{
			continue;
		}
		int t = w[x][y] - lx[x] - ly[y];
		if (0 == t)
		{
			visy[y] = true;
			if (linky[y] == -1 || find(linky[y]))
			{
				linky[y] = x;
				return true;
			}
		}
		else if (slack > t)
		{
			slack = t;
		}
	}
	return false;
}
int KM()
{
	memset(linky, -1, sizeof(linky));
	memset(ly, 0, sizeof(ly));
	int i;
	int j;
	for (i = 0; i < N; i++)
	{
		lx[i] = w[i][0];
		for (j = 1; j < M; j++)
		{
			if (w[i][j] < lx[i])
			{
				lx[i] = w[i][j];
			}
		}
	}
	int x;
	for (x = 0; x < N; x++)
	{
		while (1)
		{
			memset(visx, 0, sizeof(visx));
			memset(visy, 0, sizeof(visy));
			slack = oo;
			if (find(x))
			{
				break;
			}
			for (i = 0; i < N; i++)
			{
				if (visx[i])
				{
					lx[i] += slack;
				}
			}
			for (i = 0; i < M; i++)
			{
				if (visy[i])
				{
					ly[i] -= slack;
				}
			}
		}
	}
	int ret = 0;
	for (i = 0; i < M; i++)
	{
		if (linky[i] != -1)
		{
			ret += w[linky[i]][i];
		}
	}
	return ret;
}
int nodecnt;
int root;
struct Dic
{
	int next[256];
	int k;
}node[10000];
int NewNode()
{
	memset(node[nodecnt].next, -1, sizeof(int)* 256);
	node[nodecnt].k = -1;
	return nodecnt++;
}
int dic_insert(char * s, int &cnt)
{
	int i;
	int x = root;
	for (i = 0; s[i]; i++)
	{
		if (node[x].next[s[i]] == -1)
		{
			node[x].next[s[i]] = NewNode();
		}
		x = node[x].next[s[i]];
	}
	if (node[x].k == -1)
	{
		node[x].k = cnt++;
	}
	return node[x].k;
}
int main()
{
	int k;
	while (scanf("%d%d%d", &N, &M, &k) != EOF)
	{
		memset(w, 0x7f, sizeof(w));
		int ww;
		char s1[50];
		char s2[50];
		int acnt = 0;
		int bcnt = 0;
		int a, b;
		nodecnt = 0;
		root = NewNode();
		while (k--)
		{
			scanf("%s%s%d", s1, s2, &ww);
			a = dic_insert(s1, acnt);
			b = dic_insert(s2, bcnt);
			cout<<"a="<<a<<" b="<<b<<endl;
			w[a][b] = ww;
		}
		printf("%d\n", KM());
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章