【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; }
This passage is made by MashiroSky.