AtCoder Grand Contest 018 D - Tree and Hamilton Path
阿新 • • 發佈:2018-12-14
題目傳送門:https://agc018.contest.atcoder.jp/tasks/agc018_d
題目大意:
給定一棵\(N\)個點的帶權樹,求最長哈密頓路徑(不重不漏經過每個點一次,兩點之間轉移可以看做瞬移,對答案貢獻為兩點之間的距離)
這道題直接計算不好算,我們考慮每條邊的貢獻,基於一種貪心的思想,我們發現只要圍著樹的重心跑,就可以使每條邊得到充分利用
考慮邊i的貢獻,我們假定邊i割掉後分成兩個大小為x,y的聯通塊,那麼貢獻則為\(2*v[i]*min(x,y)\)
因為我們走的不是迴路,因此有一條邊不會被算兩次。如果樹的重心只有一個,那麼必然減去與重心相連的邊權最小的邊;如果樹的重心有兩個,減去兩重心相連的邊即可
/*program from Wolfycz*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline char gc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline int frd(){ int x=0,f=1;char ch=gc(); for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline int read(){ int x=0,f=1;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline void print(int x){ if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } const int N=2e5; int pre[(N<<1)+10],now[N+10],child[(N<<1)+10],val[(N<<1)+10]; int size[N+10],Msize[N+10]; int n,tot,rize,root; ll Ans; void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;} void insert(int x,int y,int z){join(x,y,z),join(y,x,z);} void dfs(int x,int fa,int v){ int Max=0; size[x]=1; for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){ if (son==fa) continue; dfs(son,x,val[p]),size[x]+=size[son]; Max=max(Max,size[son]); } Ans+=1ll*min(size[x],n-size[x])*v*2; Max=max(Max,n-size[x]); Msize[x]=Max; if (Max<rize){ rize=Max; root=x; } } int main(){ n=read(),rize=inf; for (int i=1;i<n;i++){ int x=read(),y=read(),z=read(); insert(x,y,z); } dfs(1,0,0); int tmp=inf; for (int p=now[root],son=child[p];p;p=pre[p],son=child[p]){ tmp=min(tmp,val[p]); if (Msize[root]==Msize[son]){ Ans-=val[p]; printf("%lld\n",Ans); return 0; } } printf("%lld\n",Ans-tmp); return 0; }