Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超級源點)


👻 👻 👻
題意:一個數組,i位置可以到達i +/- a[ i ] 位置(不越界情況下),問你每個位置要走到一個奇偶性相反的地點最少要走幾次,

在現場,,然而我真的不會哈哈哈哈我好菜🙂

主要是兩點:超級源點(多源變單源)+ 反向建邊(反向思維)

首先反向建邊,對於i位置如果可以到達i +/- a[i],建立i +/- a[i]指向i 的邊;其次建立一個超級奇數點,一個超級偶數點;
超級奇數點為例,建立起由他指向所有奇數點的邊,從該點出發,配合我們建立的反向邊,如果可以到達某個偶數點,求得的距離肯定是所有能到達他的奇數點中最小的(最短路中任意一條子路最短)

//n+1奇數0偶數超級源點
int n,a[MAXN];
vector<pii>edge[MAXN];
int dis[MAXN],vis[MAXN],ans[MAXN];
void spfa(int u)
{
    rep(i,n+2) dis[i]=1<<30,vis[i]=0;
    queue<int>q;q.push(u);
    dis[u]=0;vis[u]=1;
    while(q.size())
    {
        u=q.front(),q.pop();vis[u]=0;
        for(auto x:edge[u])
        {
            int v=x.first;
            if(dis[v]>x.second+dis[u])
            {
                dis[v]=x.second+dis[u];
                if(vis[v]==0) vis[v]=1,q.push(v);
            }
        }
    }
}
int main()
{
    fast;
    cin>>n;
    rpp(i,n)
    {
        cin>>a[i];
        if(i+a[i]<=n) edge[i+a[i]].push_back(make_pair(i,1));
        if(i-a[i]>=1)  edge[i-a[i]].push_back(make_pair(i,1));
    }
    rpp(i,n)
    {
        if(a[i]%2) edge[n+1].push_back(make_pair(i,0));
        else edge[0].push_back(make_pair(i,0));
        ans[i]=-1;
    }
    spfa(0);
    rpp(i,n) if(a[i]%2==1&&dis[i]!=1<<30) ans[i]=dis[i];
    spfa(n+1);
    rpp(i,n) if(a[i]%2==0&&dis[i]!=1<<30) ans[i]=dis[i];
    rpp(i,n) cout<<ans[i]<<" ";
    cout<<endl;
    //stop;
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM