【uoj126】 NOI2013—快餐店

http://uoj.ac/problem/126 (题目链接)

题意

  求基环树直径。

Solution

  zz选手迟早退役,唉,右转题解→_→:LCF

细节

  拓扑排序的时候度数为0时入队。我在想什么w(゚Д゚)w

代码

// uoj126
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf (1ll<<30)
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;

const int maxn=100010;
LL f[maxn][2],W[2][maxn],mx[2][maxn],suf[maxn],pre[maxn],deep[maxn];
LL ans,E;
int cnt,m,n,dag[maxn],head[maxn],vis[maxn],a[maxn];
struct edge {int to,next,w;}e[maxn<<1];

void link(int u,int v,int w) {
	e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
	e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
}
void topsort() {
	queue<int> q;
	for (int i=1;i<=n;i++) if (dag[i]==1) q.push(i);
	while (!q.empty()) {
		int x=q.front();q.pop();dag[x]--;
		for (int i=head[x];i;i=e[i].next)
			if (dag[e[i].to]) if (--dag[e[i].to]==1) q.push(e[i].to);
	}
}
void dfs(int x,int fa) {
	for (int i=head[x];i;i=e[i].next) if (!dag[e[i].to] && e[i].to!=fa) {
			deep[e[i].to]=deep[x]+e[i].w;
			dfs(e[i].to,x);
			if (f[x][0]<f[e[i].to][0]+e[i].w) f[x][1]=f[x][0],f[x][0]=f[e[i].to][0]+e[i].w;
			else if (f[x][1]<f[e[i].to][0]+e[i].w) f[x][1]=f[e[i].to][0]+e[i].w;
		}
	ans=max(ans,f[x][0]+f[x][1]);
}
void dp(int x) {
	vis[x]=1;
	int t=++m;a[m]=x;
	for (int i=head[x];i;i=e[i].next) if (dag[e[i].to] && !vis[e[i].to]) {
			W[0][m+1]=W[0][m]+e[i].w;
			dp(e[i].to);
			W[1][t]=W[1][t+1]+e[i].w;
		}
	for (int i=head[x];i;i=e[i].next) if (dag[e[i].to]) E+=e[i].w;
}
void circle() {
	LL tmp;
	pre[1]=tmp=mx[0][1]=f[a[1]][0]+W[0][1];
	for (int i=2;i<=m;i++) {
		pre[i]=max(pre[i-1],tmp+f[a[i]][0]+W[0][i]);
		mx[0][i]=max(mx[0][i-1],f[a[i]][0]+W[0][i]);
		tmp=max(tmp,f[a[i]][0]-W[0][i]);
	}
	suf[m]=tmp=mx[1][m]=f[a[m]][0]+W[1][m];
	for (int i=m-1;i;i--) {
		suf[i]=max(suf[i+1],tmp+f[a[i]][0]+W[1][i]);
		mx[1][i]=max(mx[1][i+1],f[a[i]][0]+W[1][i]);
		tmp=max(tmp,f[a[i]][0]-W[1][i]);
	}
	LL d=pre[m];E=E/2-W[0][m];
	for (int i=1;i<m;i++)
		d=min(d,max(E+mx[0][i]+mx[1][i+1],max(pre[i],suf[i+1])));
	ans=max(ans,d);
}
int main() {
	scanf("%d",&n);
	for (int u,v,w,i=1;i<=n;i++) {
		scanf("%d%d%d",&u,&v,&w);
		link(u,v,w);dag[u]++,dag[v]++;
	}
	topsort();
	for (int i=1;i<=n;i++) if (dag[i]) dfs(i,0);
	for (int i=1;i<=n;i++) if (dag[i]) {dp(i);break;}
	circle();
	printf("%.1lf",ans/2.0);
	return 0;
}

 

posted @ 2017-03-09 08:55  MashiroSky  阅读(227)  评论(2编辑  收藏  举报