LA 5713 - Qin Shi Huang's National Road System(HDU 4081) MST

LA:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3714

HDU:http://acm.hdu.edu.cn/showproblem.php?pid=4081

题目大意:

秦始皇要在n个城市之间修筑一条道路使得任意两个城市均可连通。有个道士可以用法力帮忙修一条路。秦始皇希望其他的道路总长B最短且用法术连接的两个城市的人口之和A尽量大,因此下令寻找一个A / B的最大方案。

思路:

先求出MST,然后枚举用法术修哪一条边。那么,法术修的边显然应该是MST中连接两个点 u ,v中最大的一条边。

所以对MST使用DFS,当访问一个新结点cur时候,考虑所有已经访问过的老结点x,更新f(x,u)=max( f(x,v) ,w(u,v) );其中v是u的老结点。

这样,枚举任意的两个城市,ans = max(ans, (p[i].num+p[j].num) / (mstlen - dp[i][j]));   p[i].num为城市i人数,mstlen为最小生成树的长度,dp[i][j]就是上面说的连接i 和j 最大的一条边。

下次直接用vector的了,好多的len什么的。。。



#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=1000+10;
int n;
int p_len,e_len,len;//点的数目,各个点距离的数目,MST的邻接表边数,dfs的顶点数
int fa[MAXN],head[MAXN];
double dp[MAXN][MAXN],mstlen;
int find(int cur)
{
	return cur==fa[cur]? cur : fa[cur]=find(fa[cur]);
}
struct point       //记录各个城市的坐标和人口
{
	int x,y;
	int num;
}p[MAXN];
struct edge			//化坐标为距离求MST
{
	int from,to;
	double	dis;
	bool operator<(const edge &x)const{
		return dis<x.dis;
	}
}e[MAXN*MAXN];
struct edge2		//MST邻接表
{
	int to,next;
	double val;
}e2[MAXN*2];

void add(int from,int to,double val)
{
	e2[len].to=to;
	e2[len].val=val;
	e2[len].next=head[from];
	head[from]=len++;
}
//当访问一个新结点cur时候,考虑所有已经访问过的老结点x,更新f(x,u)=max( f(x,v) ,w(u,v) );
//其中v是u的老结点。
vector<int> nodes;
void dfs(int cur,int fa,double dis)
{
	for(int i = 0; i < nodes.size(); i++) {
		int x = nodes[i];
		dp[cur][x] = dp[x][cur] = max(dp[x][fa], dis);
	}
	nodes.push_back(cur);
	for(int i=head[cur];i!=-1;i=e2[i].next)
	{
		int id=e2[i].to;
		if(id != fa)	dfs(id,cur,e2[i].val);
	}

}
//求MST,并且记录
void kruskal()
{
	memset(head,-1,sizeof(head));
	for(int i=0;i<n;i++)
		fa[i]=i;

	int &len=e_len;
	for(int i=0;i<n;i++)
		for(int j=i+1;j<n;j++)
		{
			e[len].from=i;
			e[len].to=j;
			e[len++].dis = sqrt( (double)(p[i].y-p[j].y)*(p[i].y-p[j].y)
				+(double)(p[i].x-p[j].x)*(p[i].x-p[j].x) );
		}

		int cnt=0;
		mstlen=0;
		sort(e,e+len);
		for(int i=0;i<len;i++)
		{
			int x=e[i].from,y=e[i].to;
			int root_x=find(x),root_y=find(y);
			if(root_x==root_y) continue;
			mstlen+=e[i].dis;
			fa[root_x]=root_y;
			add(x,y,e[i].dis);		//建立MST的邻接表
			add(y,x,e[i].dis);
			if(++cnt > n-1)		break;
		}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		len=e_len=p_len=0;
		memset(dp,0,sizeof(dp));
		nodes.clear();

		scanf("%d",&n);
		for(int i=0;i<n;i++)	
			scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].num);
			
	
		kruskal();

		dfs(0,-1,0);
		double ans = -1;
		for(int i = 0; i < n; i++)
			for(int j = i+1; j < n; j++) {
				ans = max(ans, (p[i].num+p[j].num) / (mstlen - dp[i][j]));
			}
			printf("%.2lf\n", ans);
	}
	return 0;
}



你可能感兴趣的:(编程,ACM,MST,la)