第一次自己手打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; }