题解-bzoj4061 CERC-2012Farm and Factory

Problem

Please contact lydsy2012@163.com!

题意概要:给定\(n\)\(m\)边无向图,设定两个起点为\(1,2\),现要求在图中增加一个点,并将这个点与其他\(n\)个点每个点连一条边(共\(n\)条),要求连完边后在新的图中从原来\(n\)个点到任一起点的最短路不一定经过新点,最小化连的\(n\)条边的权值和

Solution

超好玩的一道题

\(a_i,b_i\)分别表示从\(1,2\)出发到达\(i\)节点的最短路,设新增节点为\(t\)\(d_i\)表示从\(t\)\(i\)所连的边

发现由于最短路不能经过\(t\),所以

\(d_1+d_i\geq a_i\\d_2+d_i\geq b_i\)

\(d_i\geq \max(a_i-d_1,b_i-d_2)\)

假定已经确定了\(d_i\),希望\(d_1\)最小,发现若\(d_1> a_i+d_i\)\(d_1=a_i+d_i\)是等价的,因为即便\(d_1\)再大,在考虑后面的点时\(a_i+d_i\)会代替\(d_1\)来计算后面的限制,所以有\(d_1\leq a_i+d_i\),同理可得

\(d_1\leq a_i+d_i\\d_2\leq b_i+d_i\)

综上,可得

\(d_i\geq \max(a_i-d_1,d_1-a_i,b_i-d_2,d_2-b_i)=\max(|a_i-d_1|,|b_i-d_2|)\)

然后要最小化\(\sum d_i\),假定已经确定\(d_1,d_2\),则每个\(d_i\)一定取不等式的等号时最优,即要求最小化的式子为\(\sum \max(|a_i-d_1|,|b_i-d_2|)\)

现在只需要确定\(d_1,d_2\)了。将这个东西放在二维平面上,即有\(n\)个点\((a_i,b_i)\),发现上面的式子就是\((d_1,d_2)\)关于\(n\)个点的切比雪夫距离

问题转化为确定一个点\((d_1,d_2)\)使得这个点到\(n\)个点的切比雪夫距离和最小。这是个经典问题,可以将坐标轴旋转\(45°\)将切比雪夫距离转化为曼哈顿距离

最小化一个点到\(n\)个点的曼哈顿距离之和可以将横纵坐标拆开分别取最小,即横坐标取\(n\)个点横坐标的中位数,纵坐标取\(n\)个点纵坐标的中位数

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

inline void read(int&x){
	char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
	while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
}

const int N=101000,M=301000;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct Edge{int v,nxt,w;}a[M+M];
ll A[N],B[N];int head[N];
int n,m,_;

namespace SpFa{
	int top;
	struct node{
		int x;ll v;
		inline node(){}
		inline node(const int&X,const ll&V):x(X),v(V){}
	}h[M];
	inline void push(node nw){
		h[++top]=nw;
		int pp=top;
		while(pp>1&&h[pp].v<h[pp>>1].v)
			swap(h[pp],h[pp>>1]),pp>>=1;
	}
	inline void pop(){
		int pp=1;
		h[1]=h[top--];
		while(((pp<<1)<=top&&h[pp].v>h[pp<<1].v)||((pp<<1|1)<=top&&h[pp].v>h[pp<<1|1].v)){
			pp<<=1;
			if(h[pp].v>h[pp|1].v)pp|=1;
			swap(h[pp],h[pp>>1]);
		}
	}

	void main(int s,ll*dis){
		for(int i=1;i<=n;++i)dis[i]=inf;
		h[top=1]=node(s,0ll),dis[s]=0;
		node nw;
		while(top){
			nw=h[1];pop();
			for(int i=head[nw.x];i;i=a[i].nxt)
				if(dis[a[i].v]>dis[nw.x]+a[i].w){
					dis[a[i].v]=dis[nw.x]+a[i].w;
					push(node(a[i].v,dis[a[i].v]));
				}
		}
	}
}

void init(){
	read(n),read(m),_=0;
	for(int i=n;i;--i)head[i]=0;
	for(int i=1,u,v,w;i<=m;++i){
		read(u),read(v),read(w);
		a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;
		a[++_].v=u,a[_].w=w,a[_].nxt=head[v],head[v]=_;
	}
}

void work(){
	ll x,y,Ans=0ll;
	for(int i=n;i;--i)
		x=A[i],y=B[i],A[i]=x+y,B[i]=x-y;
	sort(A+1,A+n+1);sort(B+1,B+n+1);
	x=A[n+1>>1],y=B[n+1>>1];
	for(int i=n;i;--i)
		Ans+=abs(A[i]-x)+abs(B[i]-y);
	printf("%.9lf\n",0.5*Ans/n);
}

int main(){
	int T;read(T);
	while(T--){
		init();
		SpFa::main(1,A);
		SpFa::main(2,B);
		work();
	}return 0;
}
posted @ 2019-01-02 16:33  oier_hzy  阅读(311)  评论(0编辑  收藏  举报