codeforces#689BMike and Shortcuts

最近忙于写题和被虐,还有懒,好久没有更新博客了,昨天被虐了一整天,整个人都是迷茫状态,好好补cf吧

发现挺有意思的

这题就是cur点可以到cur-1,cur+1,a[cur]三个位置,求最短路径问题

题目数据量较大,当时没想到可以用bfs,也是好久没有用纯搜索了,时间复杂度不会算呀,我以为会超的orz

所以妥妥去想dp,然后没用想到题目可以往回走,妥妥wa,今天下午也是这样,wa看不出来那里错了,然后陷入到底是程序错了还是题目看错的尴尬局面,然后就懵逼,之前花了太多精力,后来就完全失去战斗能力了

回到这题

我用bfs实现了一遍,等下再用dij再实现一遍

本质是就是求单源最短路径的问题,我也是没想到,至于边的数目,只要记录最短条的就可以了,也就是权值为1的,dij算法的赋值度为O(n+E),这里每个点最多散发三条边,也就总共2n条,也就是O(3*n)的复杂度

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

const int inf = 0x3f3f3f3f;
const int MAXN = 2e5+100;

int a[MAXN],dp[MAXN];
int vis[MAXN];
int n;
queue<int >Q;


void bfs(int x){
    Q.push(x);
    while(!Q.empty()){
        int fro = Q.front();
        Q.pop();
        if(vis[fro])continue;
        vis[fro] = 1;
        for(int i=-1;i<=1;i++){
            if(i==0){
               if(dp[fro]+1<dp[a[fro]]){
                    dp[a[fro]] = dp[fro]+1;
                    Q.push(a[fro]);
               }
            }else{
                if(fro+i>0&&fro+i<=n&&dp[fro]+1<dp[fro+i]){
                    dp[fro+i] = dp[fro]+1;
                    Q.push(fro+i);
                }
            }
        }
    }
}

int main()
{
    //int n;
    scanf("%d",&n);
    for(int i=0;i<MAXN;i++)dp[i] = inf;
    dp[1] = 0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    bfs(1);
    printf("%d",dp[1]);
    for(int i=2;i<=n;i++)printf(" %d",dp[i]);
    cout<<endl;
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 后续:dij搞了一个小时左右,发现一个坑点,这个图是单向的,习惯性套了模板,建立双向图,直接跪了,竟然没有发现,幸好前面用dfs实现过一遍,细路比较清晰,不然都不知道错在哪

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>

using namespace std;

const int inf = 0x3f3f3f3f;
const int MAXN = 2e5+100;

struct edge{
    int u,v,dist,next;
}E[4*MAXN];

struct hn{
    int u,dist;
    bool operator < (const hn &rhs)const{
        return dist>rhs.dist;
    }
};

int a[MAXN];
int first[MAXN];
int top;
int vis[MAXN];
int d[MAXN];
int n;
priority_queue<hn>Q;

void init(){
    memset(first,-1,sizeof first);
    top = 0;
    for(int i=0;i<MAXN;i++)d[i] = inf;
    memset(vis,0,sizeof vis);
}

void addedge(int u,int v,int w){
    edge a;
    a.u = u;
    a.v = v;
    a.dist = w;
    a.next = first[u];
    first[u] = top;
    E[top++] = a;
}

void dij(int x){
    d[x] = 0;
    hn t;
    t.dist = 0;
    t.u = x;
    Q.push(t);
    while(!Q.empty()){
        hn fro = Q.top();
        Q.pop();
        int u = fro.u;
        if(vis[u])continue;
        vis[u] = 1;
        for(int i=first[u];i!=-1;i=E[i].next){
            int v = E[i].v;
            if(d[v]>d[u]+1){
                d[v] = d[u]+1;
                t.dist = d[v];
                t.u = v;
                Q.push(t);
            }
        }
    }
}

int main()
{
    init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        for(int j=-1;j<=1;j++){
            if(j==0){
                if(a[i]!=i){
                    addedge(i,a[i],1);
                    //addedge(i,a[i],1);
                }
            }else if(i+j<=n&&i+j>0){
                addedge(i,i+j,1);
                //addedge(i+1,i,1);
            }
        }
    }
    dij(1);
    printf("%d",d[1]);
    for(int i=2;i<=n;i++)printf(" %d",d[i]);
    cout<<endl;
    return 0;
}
View Code

 

posted @ 2016-07-24 01:55  iEdson  阅读(238)  评论(0编辑  收藏  举报