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; }
后续: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; }
在一个谎言的国度,沉默就是英雄