首页 > 其他分享 >[TopCoder 13001] BigO 题解

[TopCoder 13001] BigO 题解

时间:2023-10-27 23:44:06浏览次数:45  
标签:int 题解 路径 SCC stk ++ 13001 low TopCoder

[TopCoder 13001] BigO 题解

题目描述

给定一张有向图,当 \(L\) 趋近于无穷大时,长度为 \(L\) 的路径条数有 \(S\) 条,此时若 \(S = O(L^k)\),输出 \(k\),否则如果没有多项式的大 O 表示法,输出 \(-1\)。

指数情况

首先如果一张图中存在如下强连通分量,则 \(S = O(2^L)\)。

image

因为每次到 1 号点的时候都有两种选择,一种是直接回到 2,另一种是通过 3 绕回 2,从 2 回到 1 只有一种可能,所以按大 O 表示法,忽略常数,\(S = O(2^L)\)。

大胆猜测,对于一个 SCC,如果它不恰好为一个环,则它的路径条数是指数级别的。

以下给出证明:

image

如果一个 SCC 不是环,那么它的环上一定有一条伸出去的边,这条边连到的节点如果不在环上,那么一定能够找到一条路径回到 SCC,这条路径就形成了上图中的 \(a\rightarrow b\)。

如果从 \(b\) 出发,有两种路径回来,一个是经过 ... 所代表的路径,一个是经过 \(2\rightarrow 3\rightarrow 4\) 所代表的路径,它们的长度都是 \(O(n)\) 级别的,那么长度为 \(L\) 的路径条数就是 \(O(2^{\frac{L}{n}})\) 级别的,省略掉 \(n\),就是 \(O(2^L)\) 级别的。

多项式情况

分类讨论以下

\(O(L^0)\)

如果图中只有单个的环,那么只有一种走法就是一直绕,所以路径条数是常数条的,可以写作 \(O(L^0)\)。

\(O(L)\)

如果一个环 \(A\) 指向了另一个环 \(B\),那么如果从环 \(A\) 出发,我们可以选择绕不超过 \(\lfloor\dfrac{L}{|A|}\rfloor\) 次环 \(A\) 再走到环 \(B\),对于 \(L\) 而言,\(|A|\) 是常数,所以最后路径条数就是 \(O(L)\) 的。

\(O(L^k)\)

这种情况出现当且仅当存在一条链,并且链上 SCC 大小 \(> 1\) 的 SCC 个数为 \(k\)。

可以感性理解,类比上述情况。

综上所述

SCC 缩点之后,一定会形成一张 DAG,这个 DAG 上有很多条链,而多条链互相是不会影响的,由于大 O 表示法只保留最大的指数,所以最终答案就是 DAG 上的最长链长度,注意这里长度的定义是链上 SCC 大小 \(> 1\) 的 SCC 个数,因为单点是不会产生贡献的。

C++ 实现

注意 TopCoder 的题目需要写到一个指定的类里面。

时间复杂度:\(O(n + m)\)。

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 50 + 10;

vector<int> g[N], ig[N];
int n;
void init(vector<string> G) {
    n = G.size();
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            if(G[i][j] == 'Y')
                g[i + 1].push_back(j + 1);
}

int dfn[N], low[N], timestamp, stk[N], in_stk[N], scc_cnt, sz[N], id[N], top, cnt[N];
void tarjan(int p)
{
    dfn[p] = low[p] = ++ timestamp;
    stk[++ top] = p, in_stk[p]= true;
    for(auto j : g[p]) {
        if(!dfn[j]) tarjan(j), low[p] = min(low[p], low[j]);
        else if(in_stk[j]) low[p] = min(low[p], dfn[j]);
    }
    if(dfn[p] == low[p]) {
        int y;
        scc_cnt ++;
        while(y != p) {
            y = stk[top --];
            in_stk[y] = 0, id[y] = scc_cnt, sz[scc_cnt] ++;
        } 
    }
}

int f[N];

int work() {
    for(int i = 1; i <= n; i ++)
        if(!dfn[i]) tarjan(i);
    for(int i = 1; i <= n; i ++)
        for(auto j : g[i]) {
            if(id[i] == id[j])
                cnt[id[i]] ++;
            else 
                ig[id[i]].push_back(id[j]);
        }
    for(int i = 1; i <= scc_cnt; i ++)
        if(cnt[i] > sz[i])
            return -1;
    int ans = 0;
    memset(f, -0x3f, sizeof f);
    for(int i = 1; i <= scc_cnt; i ++) {
        f[i] = -1;
        for(auto j : ig[i])
            f[i] = max(f[i], f[j]);
        f[i] += (sz[i] > 1);
        ans = max(ans, f[i]);
    }
    return ans;
}

class BigO {
    public :
        int minK(vector<string> graph) {
            init(graph);
            return work();
        }
} ;

标签:int,题解,路径,SCC,stk,++,13001,low,TopCoder
From: https://www.cnblogs.com/MoyouSayuki/p/17793376.html

相关文章

  • P7650 题解
    非常好题目,第一步都想不出来。可以观察出来最优方案必定是从大往小将\(x\)放到\(x+1\)前,有可能不动,中间的比他小的一定要放到前面去。考虑用dp计算最小值。这里是这道题最重要的一步:相对位置的变化非常不好描述,考虑将所有数固定。一次操作改为:不影响其他其他数的位置,将一......
  • 题解 P4285 [SHOI2008] 汉诺塔
    具体思路设\(f_{i,x}\)表示\(i\)个盘子从\(x\)柱子出发的步数。设\(g_{i,x}\)表示\(i\)个盘子从\(x\)柱子出发到哪个柱子。记\(y=g_{i-1,x}\),\(z=6-x-y\)。其中,\(y\)代表将前\(i-1\)个盘子从\(x\)柱子移到的柱子,\(z\)代表剩下的那个柱子。分类讨论。若......
  • P2230 Tinux系统 题解
    传送门提供一种基于贪心的解法。首先是将\(p\)从小到大排序考虑到该系统是一棵树,所以对于系统中的每个点,我们记:\(tr_{son}\)表示该点(目录)的儿子的位置\(tr_{fa}\)表示该点(目录)的父亲的位置\(tr_{siz}\)表示该点(目录)包含的点的个数\(tr_{cnt}\)表示该点(目录)有......
  • YACS 2023年10月月赛 甲组 题解
    目前只有T2,其他题目我在看。题目链接1题目链接2题目链接3T2很简单的一道题,将图分为若干个连通块,然后分别求最小生成树。从货车运输中得到的结论,最小生成树等价于最小边权上限生成树,也就是它也能够保证选出边中最大的边权最小。而题目中明确说了这个最小生成树的权值是其中......
  • [NOI2010] 超级钢琴 题解
    [NOI2010]超级钢琴题解说点闲话原本不想写这个题解的但是看到我的代码居然长度为2048B->刚好2KiB,然后还跟题号相同QAQ题目翻译给你一段序列,求出其中从第\(1\)大到第\(k\)大的子区间的和。思路解析首先可以想到一个简单的暴力,对于每一个区间开头\(i\),和区间结尾\(j\),都求......
  • 2023 CSP-J2 T1,2,3题解
    今年的\(CSP−J\)对本蒟蒻来说有点难度。。。A[CSP-J2023]小苹果题目描述小Y的桌子上放着\(n\)个苹果从左到右排成一列,编号为从\(1\)到\(n\)。小苞是小Y的好朋友,每天她都会从中拿走一些苹果。每天在拿的时候,小苞都是从左侧第\(1\)个苹果开始、每隔\(2\)个......
  • [TJOI2013] 松鼠聚会 题解
    [TJOI2013]松鼠聚会题解切比雪夫距离切比雪夫距离指的是在平面上的两个点\((x_1,y_1)\),\((x_2,y_2)\)之间横纵坐标之差绝对值中的大者。用公式表示则是\(f(a,b)=max(|x_a-x_b|,|y_a-y_b|)\)。切比雪夫距离与曼哈顿距离之间可以相互转换切比雪夫—>曼哈顿:\((x_1,y_1)\),\((x......
  • [NOIP 2013提高组]货车运输 题解
    [NOIP2013提高组]货车运输题解前置知识Kruskal重构树(内含讲解)+任意一种LCA题目翻译\(n\)座城市,\(m\)条道路,\(q\)次询问,每次求两个点\(x,y\)之间所有路径的最小值的最大值。题目分析其实学了Kruskal重构树差不多看到这个题目就知道怎么写了。其实就是Kruskal重构树的板子,......
  • 问题解决
    pip源问题解决使用pip安装pytorch出现WARNING:Retrying(Retry(total=4,connect=None,read=None,redirect=None,status=None))报错使用换源解决问题pip3configlistpip3configsetglobal.index-urlhttps://mirrors.aliyun.com/pypi/simple/pip3configlist国内......
  • 第四章苏格拉底问答、实践过程截图、遇到问题解决问题截图,代码链接
    代码#include<stdio.h>#include<stdlib.h>#include<pthread.h>#defineN4intA[N][N],sum[N];void*func(voidarg){intj,row;pthread_ttid=pthread_self();row=(int)arg;printf("Thread%d[%lu]computessumofrow%d\n"......