您的位置:首页 > 其它

BZOJ2539: [Ctsc2000]丘比特的烦恼

2016-01-13 19:55 483 查看
第一次自己手打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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: