noi.ac NOIP2018 全國熱身賽 第四場 T1 tree
阿新 • • 發佈:2018-10-28
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