记录编号 9407 评测结果 AAAAAAAAAA
题目名称 [CTSC 2000] 丘比特的烦恼 最终得分 100
用户昵称 GravatarBYVoid 是否通过 通过
代码语言 C++ 运行时间 0.011 s
提交时间 2009-03-25 13:35:29 内存使用 0.28 MiB
显示代码纯文本
/* 
 * Problem: 丘比特的烦恼
 * Author: Guo Jiabao
 * Time: 2009.3.25 13:34
 * State: Solved
 * Memo: SPFA flow
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
const int MAXN=61,MAXL=21,INF=0x7FFFFFFF;
using namespace std;
struct Queue
{
	int Q[MAXN],Head,Tail,size;
	bool inq[MAXN];
	Queue()
	{
		memset(inq,0,sizeof(inq));
		Head=0;Tail=-1;size=0;
	}
	void ins(int p)
	{
		inq[p]=true;
		size++;
		if (++Tail>=MAXN) Tail=0;
		Q[Tail]=p;
	}
	int pop()
	{
		int r=Q[Head];
		size--;
		if (++Head>=MAXN) Head=0;
		inq[r]=false;
		return r;
	}
}Q;
struct Person
{
	char Name[MAXL];
	int x,y;
}P[MAXN];
struct edge
{
	edge *next,*op;
	int t,v,c;
};
int N,M,T,Distance,S,Tar,Ans;
int adj[MAXN][MAXN],sp[MAXN],ft[MAXN];
edge *V[MAXN],*pt[MAXN];
inline int dist2(int x1,int y1,int x2,int y2)
{
	return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
}
inline bool iscross(int a,int b,int c)
{
	if ((P[a].x-P[b].x)*(P[b].y-P[c].y) == (P[b].x-P[c].x)*(P[a].y-P[b].y)) //共线
	{
		if (P[a].y==P[c].y)
			return (P[a].x < P[b].x && P[b].x < P[c].x)||(P[c].x < P[b].x && P[b].x < P[a].x);
		else
			return (P[a].y < P[b].y && P[b].y < P[c].y)||(P[c].y < P[b].y && P[b].y < P[a].y);
	}
	return false;
}
void shot()
{
	int i,j,k;
	for (i=1;i<=N;i++)
		for (j=M;j<=T;j++)
		{
			if (dist2(P[i].x,P[i].y,P[j].x,P[j].y)>Distance*Distance)
				adj[i][j]=0;
			else
			{
				for (k=1;k<=T;k++)
					if (k!=i && k!=j && iscross(i,k,j))
						break;
				adj[i][j]=k>T?1:0;
			}
		}
}
inline int scanname(char *S)
{
	for (int i=1;i<=T;i++)
		if (strcmp(P[i].Name,S)==0)
			return i;
}
void format(char *s)
{
	for (;*s;s++)
		if (*s>='a' && *s<='z')
			*s=*s-'a'+'A';
}
void addedge(int a,int b,int c=1,int v=0)
{
	edge e1={V[a],0,b,v,c},e2={V[b],0,a,-v,0};
	V[a]=new edge(e1);
	V[b]=new edge(e2);
	V[a]->op=V[b];V[b]->op=V[a];
}
void init()
{
	int i,j,a,b,c,v;char Name[MAXL];
	freopen("cupid.in","r",stdin);
	freopen("cupid.out","w",stdout);
	scanf("%d%d",&Distance,&N);
	M=N+1;T=N+N;
	for (i=1;i<=T;i++)
	{
		scanf("%d%d%s",&P[i].x,&P[i].y,P[i].Name);
		format(P[i].Name);
	}
	shot();
	while (scanf("%s",Name)!=EOF)
	{
		if (strcmp(Name,"End")==0) break;
		format(Name);
		a=scanname(Name);
		scanf("%s",Name);format(Name);
		b=scanname(Name);
		scanf("%d",&v);
		if (a>b) {c=a;a=b;b=c;}
		if (adj[a][b]!=0)
			adj[a][b]=v;
	}
	S=0;Tar=T+1;
	for (i=1;i<=N;i++)
		for (j=M;j<=T;j++)
			if (adj[i][j])
				addedge(i,j,1,adj[i][j]);
	for (i=1;i<=N;i++)
		addedge(S,i);
	for (i=M;i<=T;i++)
		addedge(i,Tar);
}
bool spfa()
{
	int i,j;
	for (i=S;i<=Tar;i++)
		sp[i]=-INF;
	sp[S]=0;
	Q.ins(S);
	while (Q.size)
	{
		i=Q.pop();
		for (edge *k=V[i];k;k=k->next)
		{
			j=k->t;
			if (k->c>0 && sp[i]+k->v>sp[j])
			{
				sp[j]=sp[i]+k->v;
				pt[j]=k;ft[j]=i;
				if (!Q.inq[j])
					Q.ins(j);
			}
		}
	}
	return sp[Tar]!=-INF;
}
void augment()
{
	int delta=INF,cf=0,i;
	for (i=Tar;i!=S;i=ft[i])
	{
		if (pt[i]->c<delta)
			delta=pt[i]->c;
	}
	for (i=Tar;i!=S;i=ft[i])
	{
		pt[i]->c-=delta;
		pt[i]->op->c+=delta;
		cf+=delta*pt[i]->v;
	}
	Ans+=cf;
}
void SpfaFlow()
{
	while (spfa())
		augment();
}
int main()
{
	init();
	SpfaFlow();
	printf("%d\n",Ans);
	return 0;
}