记录编号 92336 评测结果 AAAAAAAAAA
题目名称 [CTSC 2000] 丘比特的烦恼 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.012 s
提交时间 2014-03-19 21:33:12 内存使用 0.35 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<map>
using namespace std;
const int SIZEN=100,INF=0x7fffffff;
int N,n;//n是男女人数
int range;//射程
map<string,int> namelist;
int x[SIZEN]={0},y[SIZEN]={0};
int fate[SIZEN][SIZEN]={0};
int slack[SIZEN]={0};
bool visit[SIZEN]={0};
int lable[SIZEN]={0};
int match[SIZEN]={0};
bool findpath(int u){
	visit[u]=true;
	for(int i=n+1;i<=2*n;i++){
		if(visit[i]||!fate[u][i]) continue;
		int t=lable[u]+lable[i]-fate[u][i];
		if(t==0){//在导出子图中
			visit[i]=true;
			if(match[i]==-1||findpath(match[i])){
				match[i]=u;
				return true;
			}
		}
		else if(slack[i]>t) slack[i]=t;
	}
	return false;
}
int KM(void){//返回最大匹配值
	memset(match,-1,sizeof(match));
	for(int i=1;i<=n;i++){
		lable[i]=-INF;
		for(int j=n+1;j<=2*n;j++){
			lable[i]=max(lable[i],fate[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		while(true){
			memset(visit,0,sizeof(visit));
			for(int j=n+1;j<=2*n;j++) slack[j]=INF;
			if(findpath(i)) break;
			int d=INF;
			for(int j=n+1;j<=2*n;j++) if(!visit[j]) d=min(d,slack[j]);
			for(int j=1;j<=n;j++) if(visit[j]) lable[j]-=d;
			for(int j=n+1;j<=2*n;j++) if(visit[j]) lable[j]+=d;
		}
	}
	int ans=0;
	for(int i=n+1;i<=2*n;i++){
		if(match[i]!=-1) ans+=fate[match[i]][i];
	}
	return ans;
}
int dist2(int a,int b){
	return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
void lowercase(string &s){
	for(int i=0;i<s.size();i++) if('A'<=s[i]&&s[i]<='Z') s[i]+=('a'-'A');
}
bool cross(int a,int b,int c){//b是否在ac连线上
	if((y[b]-y[a])*(x[c]-x[b])!=(y[c]-y[b])*(x[b]-x[a])) return false;//不共线
	if(y[a]==y[c]) return (x[a]-x[b])*(x[c]-x[b])<0;
	else return (y[a]-y[b])*(y[c]-y[b])<0;
}
void init(void){
	scanf("%d%d",&range,&n);
	string str;
	for(int i=1;i<=2*n;i++){
		cin>>x[i]>>y[i]>>str;
		lowercase(str);
		namelist[str]=i;
	}
	for(int i=1;i<=n;i++) for(int j=n+1;j<=2*n;j++) fate[i][j]=fate[j][i]=1;
	string n1,n2;
	int p1,p2;
	while(true){
		cin>>n1;
		if(n1=="End") break;
		cin>>n2;
		lowercase(n1),lowercase(n2);
		p1=namelist[n1],p2=namelist[n2];
		cin>>fate[p1][p2];fate[p2][p1]=fate[p1][p2];
	}
	for(int i=1;i<=n;i++){
		for(int j=n+1;j<=2*n;j++){
			if(dist2(i,j)>range*range) fate[i][j]=fate[j][i]=0;//超出射程
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=n+1;j<=2*n;j++){
			for(int k=1;k<=2*n;k++){
				if(k==i||k==j) continue;
				if(cross(i,k,j)) fate[i][j]=fate[j][i]=0;
			}
		}
	}
}
int main(){
	freopen("cupid.in","r",stdin);
	freopen("cupid.out","w",stdout);
	init();
	printf("%d\n",KM());
	return 0;
}