把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 P1477 [NOI2008] 假面舞会

洛谷

题意

一共 $n$ 个人,一共 $m$ 条消息,$k$ 种面具。
第 $i$ 种面具可以看到第 $i+1$ 种面具,第 $k$ 种面具可以看到第 $1$ 种面具。
每条消息表示 $u$ 能看到 $v$。

问 $k$ 的最大值以及 $k$ 的最小值,并且 $k\ge 3$。

分析

首先,我们以此建图,分析一下性质。

先一步一步说结论,然后分析吧。

首先,假如说存在环,那么我们的 $k$ 必然是其长度的因数。

为什么呢,因为我们的最重要的性质就是我们第 $i$ 种可以看到 $i+1$,所以我们的种类其实也是会形成一个环的。然而我们遍历出的环的也是会经过许多轮 $k$ 的环,所以结论就可以得出了。
然而倘若存在许多个环呢,由于我们的 $k$ 是其中每一个的因子,所以 $k$ 此时就是每一个环的 $\gcd$。

第二种,就是两条首、尾相同的链。

与第一种相似的,我们长的那条链必然也是短的那条链的不断重复。所以,$k$ 也是两条链的长度差的因子。

第三种,不存在前两种。

不存在前两种,我们已经没有了数字因子上的约束。
因而,我们只有极值上的范围。
因为我们的每一种的面具必然是存在过的,所以,此时我们 $k$ 的最大值也就是每个联通块最长链的长度之和。

那我们应当如何解决呢,因为我们每一次应当处理完整一个联通块,因此,我们需要在遍历其中一个点时就将整个联通块遍历完,所以,我们将有向图转化成无向图,同时标记其是正边或是反边在转移时,将时间 $+1$ 或 $-1$ 即可。

至于我们这个联通块的最长链呢,就是最大的距离减去最小距离即可。

inline void dfs(int now,int T) {
    if(mark[now]) {
        if(T==vis[now]) return ;
        if(!flag) mn=abs(T-vis[now]);
        else mn=__gcd(mn,abs(T-vis[now]));
        flag=1;
        return ;
    }
    vis[now]=T,mark[now]=1;
    MX=max(MX,T),MN=min(MN,T);
    for(auto it:lj[now]) dfs(it.to,T+it.w);
}
posted @ 2023-08-26 21:42  djh0314  阅读(51)  评论(0)    收藏  举报  来源
浏览器标题切换
浏览器标题切换end