记录编号 347431 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2013]快餐店 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 9.843 s
提交时间 2016-11-13 10:49:07 内存使用 52.82 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef double db;
typedef long long ll;
const int N=500010;
int n,head[N],tail[N],next[N],fa[N],from[N];
struct edge{int f,t,l,o;}w[N];
void add(int f,int num){
	if (!head[f]) head[f]=tail[f]=num;
		else tail[f]=next[tail[f]]=num;
}
db min(db x,db y){return x<y?x:y;}
db max(db x,db y){return x>y?x:y;}
bool OK;
int p[N],m;db len,dis[N],up[N];//存环上的点的序列,个数,及长度 
void dfs(int x){
	for (int i=head[x];i;i=next[i])
	if (w[i].o!=from[x]){
		if (OK) return;
		if (fa[w[i].t]){
			OK=1;dis[x]=w[i].l;p[++m]=x;
			for (int v=x;v!=w[i].t;v=fa[v])
				dis[fa[v]]=dis[v]+up[v],p[++m]=fa[v];
			len=dis[w[i].t];
			return;
		}
		else{
			fa[w[i].t]=x;
			from[w[i].t]=i;
			up[w[i].t]=w[i].l;
			dfs(w[i].t);
		}
	}
}
int P;db h[N],ma[N],ci[N],Max[N],L;//到根深度,子树最大深度、次大深度,子树直径 
void dfs1(int x){
	for (int i=head[x];i;i=next[i])
	if (!fa[w[i].t]){
		fa[w[i].t]=x;
		h[w[i].t]=h[x]+w[i].l;
		dfs1(w[i].t);
		db a=ma[w[i].t]+w[i].l;
		if (a>ma[x]) ci[x]=ma[x],ma[x]=a;else
		if (a>ci[x]) ci[x]=a;
		Max[x]=max(Max[x],Max[w[i].t]);
	}
	Max[x]=max(Max[x],ma[x]+ci[x]);
}
inline db D(int x,int y){
	if (dis[x]<dis[y]) swap(x,y);
	return min(dis[x]-dis[y],len+dis[y]-dis[x]);
}
db A[N],le[N],ri[N];
int sum[N],cnt;
inline int find(db x){
	int l=1,r=cnt;
	while (l!=r){
		int mid=(l+r)>>1;
		if (x>A[mid]) l=mid+1;else r=mid;
	}
	return l;
}
bool check(db x){
	if (x>=L){//说明可行答案在环上 
		cnt=0;
		A[++cnt]=0;A[++cnt]=len;
		for (int i=1;i<=m;i++){
			db R=x-ma[p[i]];
			if (R<0) return 0;
			if (R>=len/2) le[i]=0,ri[i]=len;
				else le[i]=dis[p[i]]-R,ri[i]=dis[p[i]]+R;
			if (le[i]<0) le[i]+=len;
			if (ri[i]>len) ri[i]-=len;
			A[++cnt]=le[i];A[++cnt]=ri[i];
		}
		sort(A+1,A+cnt+1);
		for (int i=0;i<=cnt;i++) sum[i]=0;
		for (int i=1;i<=m;i++){
			int l=find(le[i]),r=find(ri[i]);
			if (le[i]<=ri[i]) sum[l]++,sum[r+1]--;
				else sum[l]++,sum[cnt]--,sum[0]++,sum[r+1]--;
		}
		if (sum[0]>=m) return 1;
		for (int i=1;i<=cnt;i++){
			sum[i]+=sum[i-1];
			if (sum[i]>=m) return 1;
		}
		return 0;
	}
	else{//说明可行答案在链上 
		db le=L;
		for (int i=1;i<=m;i++)
		if (p[i]!=P){
			if (D(P,p[i])+ma[p[i]]>x) return 0;
			le=min(le,x-D(P,p[i])-ma[p[i]]);
		}
		return le+x>=L;
	}
}
db erfen(db l,db r){
	if (r-l<=1e-2) return l;
	db mid=(l+r)/2;
	return check(mid)?erfen(l,mid):erfen(mid,r);
}
int read(){
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
int main()
{
	freopen("foodshop.in","r",stdin);
	freopen("foodshop.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++){
		w[i].f=read();w[i].t=read();w[i].l=read();
		w[i+n]=w[i];w[i].o=i+n;w[i+n].o=i;
		swap(w[i].f,w[i].t);
		add(w[i].f,i);add(w[i].t,i+n);
	}
	fa[1]=1;dfs(1);
	memset(fa,0,sizeof fa);
	for (int i=1;i<=m;i++) fa[p[i]]=p[i];
	db l=0;
	for (int i=1;i<=m;i++){
		dfs1(p[i]);l=max(l,Max[p[i]]/2);
		if (L<ma[p[i]]) L=ma[p[i]],P=p[i];
	}
	printf("%.1lf\n",erfen(l,L+len));
	return 0;
}