找回密码
 立即注册
首页 业界区 安全 P2661 [NOIP 2015 提高组] 信息传递——染色做法 ...

P2661 [NOIP 2015 提高组] 信息传递——染色做法

砂歹汤 6 天前
原题

本来想当水题刷的,结果被水题刷了。。。70到80到90到100,必须写个题解记录一下(doge)
题目分析

一句话:求一个无权有向图中的最短环路(确保有环)
tip:每一个点出度为一,那么必然有环,以样例为例如下。
1.png

思路

没必要每轮模拟全部的传送,只看某一个人的传送过程:
就1而言:他的信息一次经过1-2-4-3-2...就无法回到1处,时间理解为∞。
就2而言:2-4-3-2,需要经过3轮,时间便为3。
就4,3而言:与2一样都在环里,也是3。
就5而言:不在环里是∞。
综上最快3轮结束游戏。
tip:这些题从不同点上看会比宏观看有奇效。
接下来我就想到了用染色法(万恶的开始),Son记录i的传输对象,col记录i的颜色(col=color),依次遍历每个点,在遍历第i个点时,把i染色成1,再找下一个也就是Son,然后Son[Son]...如果发现某个p点的下一个点son[p]==1,说明已经被遍历过,侧面反映成为了环。
2.png

在找到环后对从当前的开始给环染第二遍色(p一定在环里,感性理解)每个环里的点都变成2,并且每染一次用一个变量记录,便是当前i收到自己的信息和游戏结束需要的时间。
3.png

但当时我嫌麻烦,就每读取一次i就初始化一次col[ ],结果爆掉了(难受)。所以尝试优先队列优化,果然多过了一个样例,然后艰难改到90分,最后终于修成正解!
1.减少染色次数:在原始代码中,每个节点被染色两次(1和2),优化后的代码中,每个节点只被染色一次,减少了不必要的操作。
2.最小环长度的记录:使用一个变量minn 来记录最小环的长度,避免了使用优先队列的开销。
3.循环优化:在检测环的过程中,使用 do-while 循环来确保环的长度计算正确,并且减少了不必要的条件判断。
代码过程

70分暴力染色代码如下

[code]#includeusing namespace std;const int N=20005;int ans=10000008,cnt=0;int fa[N],col[N];int main(){        int n;        cin>>n;        for(int i=1;i>fa;        }        for(int i=1;in;        for(int i=1;i>Son;        }        for(int i=1;iSon;    }        int minn=N;    for(int i=1;i
您需要登录后才可以回帖 登录 | 立即注册