HDU 6060 RXD and dividing(LCA)
阿新 • • 發佈:2017-08-04
是我 lin size include continue 最大 完全 ref bsp
【題目鏈接】 http://acm.hdu.edu.cn/showproblem.php?pid=6060
【題目大意】
給一個n個節點的樹,要求將2-n號節點分成k部分,
然後將每一部分加上節點1,求每個集合最小斯坦納樹的最大權值和。
【題解】
我們按照後序遍歷染色分組,得到的一定是最優分組,
現在考慮在不同顏色的虛樹上求路徑權值和,
我們發現每個點增加的權值是深度減去到根的路徑上已被覆蓋的長度,
這個長度等於與dfs序前繼的LCA的深度,因此我們在搜索的同時計算與dfs序前繼的LCA即可。
But,發現多校題解完全不是我想的這樣子。對於每條邊來說,他的貢獻值是min(k,size),然後dfs一遍即可,實現也很是簡單。
Amazing
【代碼】
#include <cstdio> #include <algorithm> #include <list> #include <vector> using namespace std; const int N=1000010; typedef long long LL; LL d[N]; int f[N],lst[N],c[N],st[N],en[N],dfn,size[N],son[N]; vector<int> v[N],w[N]; namespace fastIO{ #define BUF_SIZE 100000 bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if(p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if(pend==p1){ IOerror=1; return -1; } }return *p1++; } inline bool blank(char ch){ return ch==‘ ‘||ch==‘\n‘||ch==‘\r‘||ch==‘\t‘; } inline bool read(int &x){ char ch; while(blank(ch=nc())); if(IOerror)return false; for(x=ch-‘0‘;(ch=nc())>=‘0‘&&ch<=‘9‘;x=x*10+ch-‘0‘); return true; } #undef BUF_SIZE }; int n,m,x,y,z; int cnt,D[N],top[N]; LL ans; void dfs(int x){ size[x]=1; for(int i=0;i<v[x].size();i++){ int y=v[x][i]; if(y==f[x])continue; f[y]=x; D[y]=D[x]+1; dfs(y); size[x]+=size[y]; if(size[y]>size[son[x]])son[x]=y; }cnt++; if(cnt>m)cnt=1; c[x]=cnt; } void dfs1(int x,int y){ if(x==-1)return; st[x]=++dfn; top[x]=y; if(son[x])dfs1(son[x],y); for(int i=0;i<v[x].size();i++)if(v[x][i]!=son[x]&&v[x][i]!=f[x])dfs1(v[x][i],v[x][i]); en[x]=dfn; } int lca(int x,int y){ for(;top[x]!=top[y];x=f[top[x]])if(D[top[x]]<D[top[y]]){int z=x;x=y;y=z;} return D[x]<D[y]?x:y; } void dfs2(int x){ int cx=c[x]; if(lst[cx]){ int y=lst[cx]; y=lca(x,y); ans+=d[x]-d[y]; }else ans+=d[x]; lst[cx]=x; for(int i=0;i<v[x].size();i++){ int y=v[x][i],z=w[x][i]; //printf("--%d %d\n",y,z); if(y==f[x])continue; d[y]=d[x]+z; dfs2(y); } } using namespace fastIO; int main(){ while(read(n)){ read(m); ans=0; for(int i=1;i<=n;i++)v[i].clear(),w[i].clear(),lst[i]=0,son[i]=-1; for(int i=1;i<n;i++){ read(x); read(y); read(z); v[x].push_back(y); v[y].push_back(x); w[x].push_back(z); w[y].push_back(z); }dfn=cnt=0; dfs(1); c[1]=0; dfs1(1,1); dfs2(1); printf("%lld\n",ans); }return 0; }
HDU 6060 RXD and dividing(LCA)