我愛海洋的题解


记住在没有思路时使用题解,不要从它复制粘贴代码。请尊重题目和题解的作者。

在解题之前提交题解的代码会导致封禁。

作者: WillyPillow

Subtask 1

輸出 \(1\)。(WA 20%)

Subtask 2

可能性不多,手算打表。(WA 20%)

Subtask 1~4

枚舉起點和終點,BFS/DFS 距離,\(O(n^2m)\)。(TLE 80%)

Subtask 1~3

經典的 DP on DAG。因為輸入已經幫你拓樸排序好了,所以連 DFS 都不用,直接 \(dp[i] = max(\{ dp[j] + 1 | \forall j\:connected\:with\:i \land depth[j] < depth[i] \} \cup \{0\})\),\(i\) 由小到大枚舉。\(O(n)\)。(WA 60%)

Subtask 1~5

Solution 1

先拓樸排序,再套用 subtask 1 \(\sim\) 3 的作法,\(O(n)\)。(AC 100%)

Solution 2

注意到由於此題的特殊性質,可以直接對深度排序來代替拓樸排序,\(O(nlgn)\)。(AC 100%)

Solution 3

直接記憶化 DP,\(O(n)\)。(AC 100%)

標程

C++ 深度排序(by tan7680
#include<bits/stdc++.h>
using namespace std;
#define maxn 100010
#define pii pair<int,int>
#define F first
#define S second
vector<int> g[maxn];
pii a[maxn];
int dp[maxn];
main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        x=n-x+1;
        a[i]=pii(x,i);
    }
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        if(a[x].F>a[y].F)g[x].push_back(y);
        else g[y].push_back(x);
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
    {
        int mx=0,u=a[i].S;
        for(int v : g[u])mx=max(mx,dp[v]);
        dp[u]=mx+1;
    }
    int ans=0;
    for(int i=1;i<=n;i++)ans=max(ans,dp[i]);
    printf("%d\n",ans-1);
    return 0;
}
C++ 拓樸排序
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
const int mod=1e9+7;
const int INF=2147483647;
vector<int> G[100005],vv;
bool vis[100005];
void dfs(int u){
    vis[u]=1;
    for(int v:G[u]) if(!vis[v]) dfs(v);
    vv.emplace_back(u);
}
int a[100005],sz[100005];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    while(m--){
        int x,y;
        scanf("%d%d",&x,&y);
        if(a[x]<a[y]) G[x].emplace_back(y);
        else G[y].emplace_back(x);
    }
    vv.reserve(n);
    for(int i=1;i<=n;i++) if(!vis[i]){
        dfs(i);
    }
    int ans=0;
    for(int x:vv){
        int ma=0;
        for(int y:G[x]) ma=max(ma,sz[y]+1);
        sz[x]=ma;
        ans=max(ans,ma);
    }
    printf("%d\n",ans);
    return 0;
}
Scala 記憶化 DP(by WillyPillow
case class Memo[I <% K, K, O](f: I => O) extends (I => O) {
  val cache = collection.mutable.Map.empty[K, O]
  override def apply(x: I) = cache getOrElseUpdate (x, f(x))
}

object x005 extends App {
  def readL() = io.StdIn.readLine().split(" ").map(_.toInt)

  val Array(n, m), depth = readL()
  val _g = (1 to m).map(_ => readL())
  val g = _g ++ _g.map(_.reverse) groupBy (_(0))

  lazy val dp: Memo[Int, Int, Int] = Memo { x =>
    1 + g.getOrElse(x, Seq.empty).view
      .filter(y => depth(y(1) - 1) > depth(x - 1))
      .map(y => dp(y(1)))
      .fold(0)(_ max _)
  }

  println((1 to n).map(x => dp(x)).max - 1)
}

评论

目前没有评论。