NC14419. 线路规划
描述
输入描述
第一行为2个正整数N、M。
第二行为N - 1个正整数L[i],第i个正整数表示第i+1个成员的直接上司L[i]。
接下来M行每行四个正整数x[i],y[i],k[i],w[i]。
输出描述
仅一行,为特别行动组成员人数的最大值和在此前提下安装线路的最小费用之和。
示例1
输入:
5 3 1 1 2 2 5 4 3 10 1 3 1 5 2 4 2 3
输出:
5 21
说明:
设(u、v、w)表示一条u到v,费用为w的线路。C++14(g++5.4) 解法, 执行用时: 1321ms, 内存消耗: 73564K, 提交时间: 2019-03-01 16:37:45
#include<cstdio> #include<algorithm> using namespace std; int gi(){ int x=0,w=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')w=0,ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } #define ll long long const int N=3e5+5; vector<int>E[N];int n,m,lg[N],fa[18][N],ufs[18][N],sz[N],ans1;ll val[N],ans2; struct node{ int x,y,k,z; bool operator < (const node &b)const {return z<b.z;} }a[N]; void dfs(int u){ for(int v:E[u]){ fa[0][v]=u; for(int i=1;i<18;++i)fa[i][v]=fa[i-1][fa[i-1][v]]; dfs(v); } } int find(int x,int *f){return x==f[x]?x:f[x]=find(f[x],f);} void solve(int x,int y,int z,int d){ if(find(x,ufs[d])==find(y,ufs[d]))return; int fx=find(x,ufs[d]),fy=find(y,ufs[d]); if(sz[fx]>sz[fy])swap(fx,fy); ufs[d][fx]=fy; if(!d)sz[fy]+=sz[fx],val[fy]+=val[fx]+z; else solve(x,y,z,d-1),solve(fa[d-1][x],fa[d-1][y],z,d-1); } int getf(int x,int d){ for(int i=0;i<18;++i)if(d>>i&1)x=fa[i][x]; return x; } int main(){ n=gi();m=gi(); for(int i=2;i<=n;++i)E[gi()].push_back(i),lg[i]=lg[i>>1]+1; dfs(1); for(int i=0;i<18;++i)for(int j=1;j<=n;++j)ufs[i][j]=j; for(int i=1;i<=n;++i)sz[i]=1; for(int i=1;i<=m;++i)a[i]=(node){gi(),gi(),gi(),gi()}; sort(a+1,a+m+1); for(int i=1;i<=m;++i){ int x=a[i].x,y=a[i].y,k=a[i].k,z=a[i].z; int t=lg[k]; solve(x,y,z,t);solve(getf(x,k-(1<<t)),getf(y,k-(1<<t)),z,t); // for(int j=0;j<18;++j) // if(k>>j&1) // solve(x,y,z,j),x=fa[j][x],y=fa[j][y]; } for(int i=1;i<=n;++i) if(find(i,ufs[0])==i) if(sz[i]>ans1) ans1=sz[i],ans2=val[i]; else if(sz[i]==ans1) ans2=min(ans2,val[i]); printf("%d %lld\n",ans1,ans2);return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 1434ms, 内存消耗: 53476K, 提交时间: 2020-03-27 11:54:31
#include<bits/stdc++.h> using namespace std; const int maxn=252505; typedef long long ll; struct node { int x,y,k,w; friend bool operator<(node n1,node n2) { return n1.w<n2.w; } }edges[maxn]; int p[20][maxn],sz[maxn],fa[20][maxn]; ll cost[maxn]; int Log[maxn]; int find(int k,int x) { return x==p[k][x]?x:p[k][x]=find(k,p[k][x]); } void merge(int k,int x,int y,int w) { int f1=find(k,x),f2=find(k,y); if(f1!=f2) { p[k][f1]=f2; if(!k) { sz[f2]+=sz[f1]; cost[f2]+=cost[f1]+w; return; } merge(k-1,x,y,w); merge(k-1,fa[k-1][x],fa[k-1][y],w); } } int main() { int n,m,x; scanf("%d%d",&n,&m); sz[1]=1; for(int i=2;i<=n;i++) scanf("%d",&fa[0][i]); for(int i=2;i<=n;i++) Log[i]=Log[i>>1]+1,sz[i]=1; for(int j=0;j<Log[n];j++) for(int i=1;i<=n;i++) fa[j+1][i]=fa[j][fa[j][i]]; for(int j=0;j<20;j++) for(int i=1;i<=n;i++) p[j][i]=i; for(int i=0;i<m;i++) cin>>edges[i].x>>edges[i].y>>edges[i].k>>edges[i].w; sort(edges,edges+m); for(int i=0;i<m;i++) { int k=Log[edges[i].k]; merge(k,edges[i].x,edges[i].y,edges[i].w); int len=edges[i].k-(1<<k); int u=edges[i].x,v=edges[i].y; for(int j=k;j>=0;j--) { if((len>>j)&1) u=fa[j][u],v=fa[j][v]; } merge(k,u,v,edges[i].w); } int ans=0; for(int i=1;i<=n;i++) if(p[0][i]==i&&(sz[ans]<sz[i]||(sz[ans]==sz[i]&&cost[ans]>cost[i]))) ans=i; printf("%d %lld\n",sz[ans],cost[ans]); }