1. 程式人生 > >noi.ac NOIP2018 全國熱身賽 第四場 T1 tree

noi.ac NOIP2018 全國熱身賽 第四場 T1 tree

etc long class 成了 clas algorithm inf max getchar

技術分享圖片

技術分享圖片

【題解】

  考慮從小到大枚舉邊權,按順序加邊。

  當前樹被分成了若幹個聯通塊,若各個塊內的點只能跟塊外的點匹配,那麽最終的min g(i,pi)一定大於等於當前枚舉的邊。

  判斷各個聯通塊內的點是否全部能跟塊外的點匹配,只需比較sum-cnt[i]、size[i],其中sum是所有x的和,cnt是塊內x的和,size是聯通塊大小。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 #define rg register
 6
#define N 200010 7 using namespace std; 8 int n,ans,f[N],siz[N]; 9 LL cnt[N],sum; 10 struct edge{int u,v,w;}e[N]; 11 inline int read(){ 12 int k=0,f=1; char c=getchar(); 13 while(c<0||c>9)c==-&&(f=-1),c=getchar(); 14 while(0<=c&&c<=9)k=k*10+c-0,c=getchar();
15 return k*f; 16 } 17 inline bool cmp(edge a,edge b){return a.w<b.w;} 18 int find(int x){return f[x]==x?x:f[x]=find(f[x]);} 19 int main(){ 20 n=read(); 21 for(rg int i=1;i<=n;i++) f[i]=i,siz[i]=1; 22 for(rg int i=1;i<n;i++) e[i].u=read(),e[i].v=read(),e[i].w=read(); 23 for
(rg int i=1;i<=n;i++) cnt[i]=read(),sum+=cnt[i]; 24 sort(e+1,e+n,cmp); 25 for(rg int i=1;i<n;i++){ 26 // printf("%d\n",e[i].w); 27 int u=find(e[i].u),v=find(e[i].v); 28 if(sum-cnt[u]>=siz[u]&&sum-cnt[v]>=siz[v]) ans=max(ans,e[i].w); 29 else break; 30 f[u]=v; cnt[v]+=cnt[u]; siz[v]+=siz[u]; 31 if(sum-cnt[v]<siz[v]) break; 32 } 33 printf("%d\n",ans); 34 return 0; 35 }

noi.ac NOIP2018 全國熱身賽 第四場 T1 tree