zoukankan      html  css  js  c++  java
  • Codeforces 1272E (Nearest Opposite Parity,反向建边)

    题意:给你n个数,每个数的值为a[i],每个点可以从i这号点跳转至(i - a[i]) 或 (i + a[i])点,点的范围为[1,n],然后问的是从偶数点跳至奇数点,从奇数点跳至偶数点的最少次数是多少?

    解答:这个题很不错,难度系数1900。让我对反向建边有了一定的认识。

    为什么需要反向建边呢?因为正向建边无法很好地做到更新当前自身u的情况,但却可以更新v最小的情况(可是所有v中的最小情况明明应该是u的最小情况,这就是正向的缺点)。而可以通过反向建边,不断更新,最后更新到目标点,该目标点已经是最优的情况了。

    关于超级源点和超级汇点:我们把所有奇数点与超级源点0相连,偶数点与超级汇点n+1相连,相连距离为0,然后分别跑Dijkstra.

    Dijkstra1(以奇数点为起点)跑出来的结果是偶数的最小情况,如果是INF那就说明转换不到输出-1;

    Dijkstra2(以偶数点为起点)跑出来的结果是奇数的最小情况,如果是INF那就说明转换不到输出-1;

    最后看自己的奇偶性输出自己的情况就行了。

    #include<bits/stdc++.h>
    #define ll long long
    #define white 0
    #define black 1
    #define grey  2
    #define endl '
    '
    #define INF 0x3f3f3f3f3f
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int maxn=3e5+5;
    int tot,head[maxn];
    struct E{
        int to,next,w;
    }edge[maxn<<1];
    void add(int u,int v,int w){
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    ll d1[maxn],d2[maxn];ll color[maxn];
    priority_queue<pair<ll,ll> >q; 
    ll n,a[maxn];
    void Dijkstra(ll s,ll *d){
        for(ll i=0;i<=n;i++) d[i]=INF,color[i]=white;
        d[s]=0;
        q.push(make_pair(0,s));
        color[s]=grey;
        while(!q.empty()){
            pair<ll,ll> f=q.top();
            q.pop();
            ll u=f.second;
            color[u]=black;
            if(d[u]<f.first*(-1)) continue;
            for(ll i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if(color[v]==black) continue;
                if(d[v]>d[u]+edge[i].w){
                    d[v]=d[u]+edge[i].w;
                    q.push(make_pair(d[v]*(-1),v));
                    color[v]=grey;
                }        
            }
        }
    }
    signed main(){
        cin>>n;memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(a[i]%2==1) add(0,i,0);
            if(a[i]%2==0) add(n+1,i,0);
            if(i+a[i]<=n) add(i+a[i],i,1);
            if(i-a[i]>=1) add(i-a[i],i,1);
        }
        Dijkstra(0,d1);
        Dijkstra(n+1,d2);
        for(int i=1;i<=n;i++){
            if(a[i]%2==1){
                if(d2[i]==INF) cout<<"-1"<<" ";
                else cout<<d2[i]<<" ";
            }else{
                if(d1[i]==INF) cout<<"-1"<<" ";
                else cout<<d1[i]<<" ";
            }
        }
        cout<<endl;
    }
    View Code
  • 相关阅读:
    通过git命令行从github或服务器上克隆、修改和更新项目
    将项目部署到 github上(部署到码云操作一样,前提是有码云账号)
    tp5中代替tp3.2中的一些方法
    关于ThinkPHP下使用Uploadify插件 仅有火狐提示HTTP Error (302)错误的解决办法
    nginx轮询宕机解决
    nginx实现动静分离
    nginx实现负载均衡
    nginx实现反向代理
    解决表单重复提交
    解决跨域问题
  • 原文地址:https://www.cnblogs.com/Anonytt/p/12831040.html
Copyright © 2011-2022 走看看