P5419 [CTSC2016]单调上升序列 题解

P5419 [CTSC2016]单调上升序列 题解

P5419 [CTSC2016]单调上升序列

构造题,思维题

先放个结论:\(n\) 个点的完全图 \(G\) 最长的单调上升路径最短为 \(n-1\)

证明的话其实就是题目里那个证明,不然他说一段废话干嘛

现在确定了最长的单调上升路径的长度,考虑怎么构造它。

两个相邻的数如果不在相邻边上,那么它俩一定不能在同一个单调上升序列中,因为在它俩之间插进来的那些数一定会破坏整条路径的单调性。

构造方法就是把 \(\frac{n(n-1)}{2}\) 条边拆成 \(n-1\) 组,每组里有 \(\frac{n}{2}\) 条边(因为保证了 \(n\) 是偶数所以 \(\frac{n}{2}\) 一定能整除),每组边的权值是连续的,即 \(v\in[(i-1)\times\frac{n}{2}+1,i\times\frac{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("\n");
    }
    return 0;
}
posted @ 2021-10-08 16:44  DReamLion  阅读(98)  评论(1编辑  收藏  举报