专栏文章

题解:P10231 [COCI 2023/2024 #4] Putovanje

P10231题解参与者 1已保存评论 0

文章操作

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

当前评论
0 条
当前快照
1 份
快照标识符
@minro5pq
此快照首次捕获于
2025/12/02 07:14
3 个月前
此快照最后确认于
2025/12/02 07:14
3 个月前
查看原文
省流:假算。
我们对于每一个 di1d_i \neq -1 的点,跑一次 BFS,最后满足所有要求的点就是答案。我们就得到了一个 O(n2)O(n^2) 的暴力。
发现 n5×104n \le 5 \times 10^4,这个做法应该很有前途。
在数据没有精心构造的情况下,直观感受,较少次 BFS 可以排除掉很多点,所以,再剩下合法的点不多的情况下,直接反过来判断这些点是否合法。
虽然很容易被卡,但是加上一些神秘的优化,在本题数据强度极低的情况下可以通过。
CPP
#include<bits/stdc++.h>
#define endl '\n'
#define debug(x) cerr<<#x<<':'<<x<<endl
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int N=5e4+5;
mt19937 rnd(time(0));
int n,m;
int a[N];
vector<int> G[N],ans;
int dis[N],vis[N];
int mp[N],tot;
int p[N];
void bfs(int s){
    queue<int> q;
    q.push(s);
    for(int i=1;i<=n;i++) vis[i]=dis[i]=0;
    vis[s]=1;
    dis[s]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int y:G[x]){
            if(!vis[y]){
                dis[y]=dis[x]+1;
                q.push(y);
                vis[y]=1;
            }
        }
    }
}
void seeyou(){
    for(int i=1;i<=n;i++){
        if(!mp[i]) continue;
        bfs(i);
        int flag=1;
        for(int j=1;j<=n;j++){
            if(a[j]==-1) continue;
            if(dis[j]!=a[j]){
                flag=0;
                break;
            }
        }
        if(flag) ans.push_back(i);
    }
    cout<<ans.size()<<endl;
    for(int x:ans) cout<<x<<' ';
}
signed main(){
    srand(time(0));
    IOS;
    cin>>n>>m;
    for(int i=1,u,v;i<=m;i++){
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) mp[i]=1,p[i]=i;
    tot=n;
    shuffle(p+1,p+n+1,rnd);
    for(int j=1;j<=n;j++){
        int i=p[j];
        if(a[i]==-1) continue;
        bfs(i);
        for(int j=1;j<=n;j++){
            if(dis[j]==a[i]) continue;
            if(mp[j]) mp[j]=0,tot--;
        }
        if(tot<=300) return seeyou(),0;
        if(1.0*clock()/CLOCKS_PER_SEC>0.9) break;
    }
    for(int i=1;i<=n;i++) if(mp[i]) ans.push_back(i);
    cout<<ans.size()<<endl;
    for(int x:ans) cout<<x<<' ';
    return 0;
}

评论

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

正在加载评论...