现在的位置: 首页 > 综合 > 正文

模拟赛 警察叔叔就是这个人!

2018年04月24日 ⁄ 综合 ⁄ 共 2319字 ⁄ 字号 评论关闭
文章目录

题目描述

魅力之都是一个有N个路口,M条双向道路连接的城市。警察叔叔绘制了一张特殊的地图,在地图上只保留了N-1条道路,我们称这些道路为【特殊道路】,要保证任意两个路口间有且仅有一条路径,且满足所有保留的道路长度之和最小。

现在要在其中一个连接有多条【特殊道路】的路口设立【根据地】,去掉【根据地】所在路口后,就会出现某些路口间无法通过【特殊道路】相互连通的情况,我们认为这时仍然能够通过【特殊道路】连通的路口属于同一个【区域】。警察叔叔希望最后每个【区域】的【特殊道路】总长尽可能平均。警察叔叔找到了hzwer,但是hzwer是个无向图和有向图都无法区分的蒟蒻,请你帮他计算出应该选择哪一个路口作为【根据地】。

(尽可能平均即权值最小,设每一块【区域】的路线总长为Length[i](包括连接【根据地】与该【区域】的边),平均路线长度为Avg=SUM{Length[i]}/区域数,权值d=∑ (Length[i]-Avg)^2 

输入格式

第1行:2个正整数N,M

第2..M+1行:每行2个整数u,v和1个实数len,表示u,v之间存在长度为len的边

输出格式

第1行:1个整数,最后选择的路口编号(存在多个可选路口时选择编号小的)

样例数据 1

输入

3 3
3 1 5
3 2 4
1 2 3
输出

2

样例数据 2

输入

3 3
2 1 825.7291
3 2 397.4120
1 3 633.1370
输出

3

备注

对于60%的数据:3 ≤ N ≤ 2,000,N-1 ≤ M ≤ 50,000

对于100%的数据:3 ≤ N ≤ 40,000,N-1 ≤ M ≤ 200,000

对于100%的数据:0 < len ≤ 100,000,000

保证不存在相同距离的线路,两个路口间可能出现多条路径,且任意点对间至少存在一条路径

题解

话说第一步是最小生成树没人不知道。n挺小的,dfs求出树上一些信息,枚举每个点即可。

考试时逗了,rest忘清零了……

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define ll long long
#define MAXM 200002
#define MAXN 40002
using namespace std;
int n,m,f[MAXN];
struct bian{int x,y; double v;} E[MAXM];
double totlen;
int zz,head[MAXN],fa[MAXN],con[MAXN],ans;
struct tree{int to,nx; double v;} e[MAXM*2];
double sum[MAXN],mind,pjlen,d,rest;
//------------------------------------------------------------------------------
bool kp(const bian &i,const bian &j) {return i.v<j.v;}
void init()
{
	scanf("%d%d",&n,&m);
	int i,x,y; double z;
	for(i=1;i<=m;i++)
	   scanf("%d%d%lf",&E[i].x,&E[i].y,&E[i].v);
	sort(E+1,E+m+1,kp);
}
void insert(int x,int y,double z)
{
	zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz;
	zz++; e[zz].to=x; e[zz].v=z; e[zz].nx=head[y]; head[y]=zz;
}
int find(int x)
{
	if(f[x]!=x) f[x]=find(f[x]);
	return f[x];
}
void klskl()
{
	int i,r1,r2;
	for(i=1;i<=n;i++) f[i]=i;
	for(i=1;i<=m;i++)
	   {r1=find(E[i].x),r2=find(E[i].y);
	    if(r1!=r2)
	       {f[r2]=r1; totlen+=E[i].v;
		    insert(E[i].x,E[i].y,E[i].v);
		   }
	   }
}
//------------------------------------------------------------------------------
void dfs(int x)
{
	int i,p;
	con[x]=1;
	if(x==1) con[x]--;
	for(i=head[x];i;i=e[i].nx)
	   {p=e[i].to;
	    if(p==fa[x]) continue;
		sum[p]+=e[i].v; con[x]++;
		fa[p]=x; dfs(p);
		sum[x]+=sum[p];
	   }
}
double sqr(double x) {return x*x;}
void work()
{
	int i,j,p;
	mind=1e20;
	for(i=1;i<=n;i++)
	   {if(con[i]<=1) continue;
	    d=0; pjlen=totlen/con[i]; rest=0;
	    for(j=head[i];j;j=e[j].nx)
	       {p=e[j].to;
		    if(p==fa[i]) continue;
		    d+=sqr(sum[p]-pjlen);
		    rest+=sum[p];
		   }
		rest=totlen-rest;
		d+=sqr(rest-pjlen);
		if(d<mind)
		   {mind=d; ans=i;}
	   }
	printf("%d\n",ans);
}
int main()
{
	init(); klskl();
	dfs(1); work();
	return 0;
}

抱歉!评论已关闭.