P5454 [THUPC2018]城市地铁规划
题意
略。
分析
\(prufer\)序列+\(dp\)。
代码
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
const int N=3005,MOD=59393;
int n,m,sum;
int dp[N],pre[N],a[N],w[N],d[N],cnt;
int pru[N],fa[N];
inline int inc(int x,int y){int tmp=x+y;return tmp>=MOD?tmp-MOD:tmp;}
void PrufertoTree(){
for(int i=1;i<=n-2;i++) d[pru[i]]++;pru[n-1]=n;
for(int i=1,now=1;i<=n-1;i++,now++){
while(d[now]) now++;
fa[now]=pru[i];
while(i<n-1&&!--d[pru[i]]&&pru[i]<now) fa[pru[i]]=pru[i+1],i++;
}
return ;
}
signed main(){
read(n),read(m);sum=(n-1)<<1;
for(int i=0;i<=m;i++) read(a[i]);
for(int i=0;i<=n;i++){
for(int j=m;j>=0;j--){
w[i]=inc(w[i]*i%MOD,a[j]);
}
}
dp[0]=n*w[1];
for(int i=2;i<=n;i++){
for(int j=i-1;j<=n-2;j++){
if(dp[j-i+1]+w[i]-w[1]>dp[j]){
pre[j]=j-i+1;
dp[j]=dp[j-i+1]+w[i]-w[1];
}
}
}
write(n-1),putchar(' '),write(dp[n-2]),putchar('\n');
int now=n-2;
while(now-pre[now]>0) d[++cnt]=now-pre[now],now=pre[now];
for(int i=1,j=1;i<=cnt;i++) while(d[i]--) pru[j++]=i;memset(d,0,sizeof(d));
PrufertoTree();
for(int i=1;i<=n-1;i++) write(i),putchar(' '),write(fa[i]),putchar('\n');
return 0;
}