BZOJ2539: [Ctsc2000]丘比特的烦恼

第一次自己手打KM


KM的思想就是每次修改标杆

http://blog.sina.com.cn/s/blog_691ce2b701016reh.html

关于KM的思想这个blog讲的很详细了

以前做poj的时候就经常去这个blog。。。

人家果然是大神 


#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
#define abs(x) ((x)<0?(-(x)):(x))
const
 int INF=1<<29;
char c;
bool flag;
inline void read(int &a)
{
	a=0,flag=false;do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
	c=(c=='-'?flag=true,getchar():c);
	while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
    a=(flag?-a:a);
}

int slack[101];
bool visx[101],visy[101];
int n,k;
int W[101][101];

struct Name
{
  char D[31];
  int len;
  inline void get()
  {
  	len=0;
   	do c=getchar();while((!(c<='z'&&c>='a'))&&(!(c<='Z'&&c>='A')));
    while((c<='Z'&&c>='A')||(c<='z'&&c>='a'))
      {
      	if(c<='z'&&c>='a')c+='A'-'a';
	    D[++len]=c;
		c=getchar();
	  }
  }	
  inline friend bool operator <(Name a,Name b)
  {
  	if(a.len^b.len)return a.len<b.len;
  	for(int i=1;i<=a.len;i++)
  	  if(a.D[i]^b.D[i])
  	     return a.D[i]<b.D[i];
  	return false;
  }
}Tp,Tp2,End;
map<Name,int>C;
int con=0;
bool Man[101];
int X[101],Y[101];
int Opt_[31];
int Lx[31],Ly[31];
bool DFS(int u)
{
	visx[u]=true;
	for(int y=1;y<=n;y++)
      if(!visy[y])
        {
        	 int tmp=Lx[u]+Ly[y]-W[u][y];
        	 if(!tmp)
        	    {
        	       visy[y]=true;
				   if(Opt_[y]==-1||DFS(Opt_[y])) 
				       return Opt_[y]=u,true;	
				}
			else if(slack[y]>tmp)slack[y]=tmp;
		}
	return false;
}


inline void KM()
{
	memset(Opt_,-1,sizeof(Opt_));
	int i,j;
	for(i=1;i<=n;i++)
	{
	  Lx[i]=-INF;
      for(j=1;j<=n;j++)
         Lx[i]=max(Lx[i],W[i][j]);
	}
   for(i=1;i<=n;i++)
     Ly[i]=0;
    for(i=1;i<=n;i++)
       {
       	 for(j=1;j<=n;j++)
       	   slack[j]=INF;
       	  while(true)
       	  {
       	  	memset(visx,false,sizeof(visx));
       	  	memset(visy,false,sizeof(visy));
		    if(DFS(i))
                   break;
                int minx=INF;
                for(int t=1;t<=n;t++)
                  if(!visy[t]&&minx>slack[t])
                     minx=slack[t];
                for(int t=1;t<=n;t++)
                  if(visx[t])Lx[t]-=minx;
                for(int t=1;t<=n;t++)
                   if(visy[t])Ly[t]+=minx;
                   else slack[t]-=minx;
 		  }
	   }
}
int main()
{
	End.len=3;
	C.clear();
	End.D[1]='E';
	End.D[2]='N';
	End.D[3]='D';
    read(k);
	read(n);
	for(int i=1;i<=n;i++)
		read(X[i]),read(Y[i]),Tp.get(),C[Tp]=++con,Man[con]=true;
	for(int i=1;i<=n;i++)
		read(X[i+n]),read(Y[i+n]),Tp.get(),C[Tp]=++con,Man[con]=false;
	while(true)
    {
    	 Tp.get();
    	 if(!(Tp<End)&&!(End<Tp))break;
    	 Tp2.get();  
    	 if(Man[C[Tp]])
    	    read(W[C[Tp]][C[Tp2]-n]);
    	 else
    	    read(W[C[Tp2]][C[Tp]-n]);
	}
	for(int i=1;i<=n;i++)
	 for(int j=1+n;j<=2*n;j++) 
	   {
	   	 for(int T=1;T<=2*n;T++)
	   	   if(T^i&&T^j)
	   	      {
	   	      	if(Y[i]-Y[j]==0||(Y[i]-Y[T])==0)
	   	           if(Y[i]-Y[j]==0&&(Y[i]-Y[T])==0&&X[T]-max(X[i],X[j])<0&&min(X[i],X[j])-X[T]<0) 
				   {   W[i][j-n]=-INF;goto loop;} 
				   else continue;
				else if((X[i]-X[j])*(Y[i]-Y[T])==(X[i]-X[T])*(Y[i]-Y[j]))	
			      if((Y[T]-max(Y[i],Y[j])<0&&min(Y[i],Y[j])-Y[T]<0)||(X[T]-max(X[i],X[j])<0&&min(X[i],X[j])-X[T]<0))
			       {   W[i][j-n]=-INF;goto loop;}
			      
			  }
		 if((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j])>k*k)
		     {W[i][j-n]=-INF;goto loop;}
		if(!W[i][j-n])
		W[i][j-n]=1;
		 loop:;
	   }
	KM();
	int ans=0;
	for(int  i=1;i<=n;i++)
	  ans+=W[Opt_[i]][i];
	printf("%d\n",ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值