专栏文章

题解:P13001 [GCJ 2022 Finals] Wonderland Chase

P13001题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@minuj92g
此快照首次捕获于
2025/12/02 08:35
3 个月前
此快照最后确认于
2025/12/02 08:35
3 个月前
查看原文
这题只需要搞明白一件事情,剩下的就是一些很简单的图论操作了。
什么时候追不到,能跑掉呢?很显然 10910^9 的次数意思是告诉我们永远都追不上才能跑掉。只有两种情况符合这种要求:
  1. Alice 与红心皇后不在一个连通块,这样皇后无论如何也跑步过来。
  2. Alice 能赶在被抓伤之前跑进一个环。因为一旦在环里面,Alice 无论如何都有一条路可以走。
否则,Alice 一定就会被追上。这时只需要找到一个点,使得Alice 能在皇后赶到之前抵达,最大化皇后赶到的时间即可。
实现起来的话,先标记所有处于环内的点。由于这是无向图,我们不用什么 tarjan 之类的算法,只需要依次移除所有度为 11 的点即可。
接下来就是跑两次 dijkstra,记录所有点距离皇后与 Alice 分别有多远,然后遍历所有点。若点处于环内,且距离 Alice 比距离皇后近,则代表 Alice 安全。否则若不在环但仍然离 Alice 更近,则更新一下答案。若皇后距离 Alice 所在的点为无穷大,则 Alice 也是安全的。
最后注意乘以 22,因为皇后动一步 Alice 也得动一步。
以下代码是处理每一个测试点的代码,注意多测清空。
CPP
cin>>j>>c>>a>>q;
while (c--){
    int u,v;
    cin>>u>>v;
    adj[u].push_back(v);
    adj[v].push_back(u);
    deg[u]++;
    deg[v]++;
}
for (int i=1;i<=j;i++) alice[i]=queen[i]=MAXN; 
queue<pair<int,int>> qq;
qq.push({0,a});
while (qq.size()){
    auto qf=qq.front();
    qq.pop();
    if (alice[qf.second]!=MAXN) continue;
    alice[qf.second]=qf.first;
    for (int i:adj[qf.second]) qq.push({qf.first+1,i});
}
qq.push({0,q});
while (qq.size()){
    auto qf=qq.front();
    qq.pop();
    if (queen[qf.second]!=MAXN) continue;
    queen[qf.second]=qf.first;
    for (int i:adj[qf.second]) qq.push({qf.first+1,i});
}
for (int i=1;i<=j;i++) cycle[i]=1;
queue<int> qqq;
for (int i=1;i<=j;i++){
    if (deg[i]==1) {
        qqq.push(i);
    }
}
while (qqq.size()){
    int qf=qqq.front();
    qqq.pop();
    vis[qf]=1;
    cycle[qf]=0;
    for (int i:adj[qf]) {
        if (!vis[i]) {
            deg[i]--;
            if (deg[i]==1) qqq.push(i);
        }
    }
}

int ans=0;
for (int i=1;i<=j;i++){
    if (alice[i]==MAXN) continue;
    if (alice[i]<queen[i]) ans=max(ans,queen[i]);
    if ((cycle[i]&&alice[i]<queen[i])||(alice[i]!=MAXN&&queen[i]==MAXN)){
        cout<<"SAFE\n";
        return ;
    }
}
cout<<ans*2<<"\n";

评论

1 条评论,欢迎与作者交流。

正在加载评论...