P5419 [CTSC2016]单调上升序列 题解
构造题,思维题
先放个结论:(n) 个点的完全图 (G) 最长的单调上升路径最短为 (n-1)。
证明的话其实就是题目里那个证明,不然他说一段废话干嘛。
现在确定了最长的单调上升路径的长度,考虑怎么构造它。
两个相邻的数如果不在相邻边上,那么它俩一定不能在同一个单调上升序列中,因为在它俩之间插进来的那些数一定会破坏整条路径的单调性。
构造方法就是把 (frac{n(n-1)}{2}) 条边拆成 (n-1) 组,每组里有 (frac{n}{2}) 条边(因为保证了 (n) 是偶数所以 (frac{n}{2}) 一定能整除),每组边的权值是连续的,即 (vin[(i-1) imesfrac{n}{2}+1,i imesfrac{n}{2}])。放边的时候保证每组中的边在图上是不相邻的即可。
为什么这样构造是对的呢?
这样构造使得最长单调上升路径上的边只能是每组出一条,不会有两条在同一组中。一共只有 (n-1) 个组,所以最长单调上升路径的长度为 (n-1)。
(code)
#include<bits/stdc++.h>
#define N 510
#define int long long
#define debug cout<<"------------------"<<endl
using namespace std;
int n;
int ans[N][N];
signed main(){
cin>>n;
for(int i=1;i<n;i++){
ans[i][n]=ans[n][i]=(i-1)*(n/2)+1;
int p=i,q=i;
for(int j=1;j<(n/2);j++){
p=((p-1==0)?n-1:p-1);
q=((q+1==n)?1:q+1);
ans[p][q]=ans[q][p]=(i-1)*n/2+j+1;
}
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
printf("%lld ",ans[i][j]);
}
printf("
");
}
return 0;
}