NOIp 2018 D2T1 旅行//未完成
这个题没有认真读的话就会写下以下的DD代码
#include<bits/stdc++.h> #define N 5010 using namespace std; int n,m; int ans[N],actr; int head[N],ectr; bool vis[N]; struct Edge{ int from,to,nxt; }edge[N<<1]; void addedge(int from,int to){ ectr++; edge[ectr].from=from; edge[ectr].to=to; edge[ectr].nxt=head[from]; head[from]=ectr; } priority_queue<Edge> q; bool operator < (Edge a,Edge b){ if(a.to != b.to) return a.to > b.to; else return a.from>b.from; } int main() { cin>>n>>m; for(int i=1;i<=m;i++) { int tra1,tra2; scanf("%d%d",&tra1,&tra2); addedge(tra1,tra2); addedge(tra2,tra1); } q.push(Edge{0,1,0}); while (actr!=n) { Edge xxx=q.top(); q.pop(); if(vis[xxx.to]) continue; vis[xxx.to]=true; ans[++actr]=xxx.to; for(int i=head[xxx.to];i;i=edge[i].nxt) q.push(edge[i]); } for(int i=1;i<=actr;i++) cout<<ans[i]<<" "; return 0; }
用单调队列维护一个边队列 然后不断从里面抓出来没有被更新的点 看上去好像很对
实际上换个题它就是对的 但是这不是换的那个题
题中说只有两种走法 一种是从当前走向一个没走过的点 另一种是从走过的回退到走过的
那就意味着 如果你回退了一步 你不能再走到一个你已经走过的点了
这就是为什么单调队列不能用的原因(而且什么玄学下标也救不了)
正解是基环树上的dfs找环断边(logn) 然后树上跑一遍dfs(n)
总复杂度为O(n*logn)
但实际上你不用找环也行 因为这题n2也能过(哈哈哈哈哈哈哈哈哈哈哈哈)
直接暴力短边VANS
但是该学的算法还是要学的 要去做那个数据加强版的
这里埋个坑 以后回来写掉
TAG:SIN_XIII ⑨