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

但是该学的算法还是要学的 要去做那个数据加强版

扫描二维码关注公众号,回复: 5168751 查看本文章

这里埋个坑 以后回来写掉

TAG:SIN_XIII ⑨

猜你喜欢

转载自www.cnblogs.com/SINXIII/p/10380929.html