codeforces 605 div3 Nearest Opposite Parity(反向建图 超级源 BFS)

题目大意:

现在有一个无权图,每个节点都是0或者1,问所有0节点到最近邻1节点的距离以及所有1节点到所有0节点的最短距离。

解题思路:

无权图最短路径很容易想到BFS,但是假如直接对每个节点都做BFS,复杂度O(N^2)会超时。另外,很容易地我们也想打一个记忆化搜索,因为有些信息是我们重复了的,比如某个0节点到1节点的最近距离,已经跑过一次了我们就不需要再跑一次。但是,问题是这里我们用BFS,我们应该很少见过用BFS打记忆化搜索的。所以记搜也否决。

这里其实我们可以反过来思考。例如我们想得到1到最近邻的0,那么我们可不可以从0出发呢,然后反向建图,那么我们需要从哪一个0出发呢?这里,很自然地我们可以建一个超级源,超级源连向所有为0的节点,同时它的边权为0,这时候跑一次BFS,我们就能得到所有节点为1的最近邻的0节点的距离了。

为什么有这个结论。我们再仔细思考,BFS是求无权最短路的。假如我们得到所有1节点到根节点(超级源)的最短距离,是不是相当于得到了所有1节点到0节点的最短距离呢。

这里有一个很好的把所有0节点拿出来建一个 超级源的思路,通过建了这个超级源,我们得到了所有1节点到0节点的最短距离。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
vector<int> odd;
vector<int> even;
vector<vector<int>> gra(MAXN);
vector<int> ans(MAXN,0);
void bfs(vector<int> start,vector<int> end){
    queue<int> q;
    int dist[MAXN];
    memset(dist,-1,sizeof(dist));
    for(auto it:start){
        dist[it]=0;
        q.push(it);
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=0;i<(int)gra[u].size();i++){
            int nx=gra[u][i];
            if(dist[nx]==-1){
                dist[nx]=dist[u]+1;
                q.push(nx);
            }
        }
    }
    for(auto it:end){
        ans[it]=dist[it];
    }
}
int main(){
    int n;cin>>n;
    for(int i=0;i<n;i++){
        int t;cin>>t;
        if(t&1)odd.push_back(i);
        else even.push_back(i);
        if(i+t<n)gra[i+t].emplace_back(i);
        if(i-t>=0)gra[i-t].emplace_back(i);
    }
    bfs(odd,even);
    bfs(even,odd);
    for(int i=0;i<n;i++)cout<<ans[i]<<" ";
    cout<<endl;
	return 0;
}
发布了171 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/FrostMonarch/article/details/103795508
今日推荐