Codeforces Detour(Dijkstra +爆搜)

28 篇文章 0 订阅
24 篇文章 0 订阅

Description

After last year’s edition of the BAPC, you are still stuck in Delft. In order to participate again this year, you are going to Amsterdam by bus. During the journey you look out of the window and look for traffic signs that point in the direction of Amsterdam. To your surprise, you notice that the bus is never taking the roads that are pointed out by the signs! You think that the bus company might have chosen a route such that, at no intersection, the bus goes in the direction that is pointed to by the signs. Your friends, however, find this very unbelievable, and don’t think this is possible. Can you figure out whether there exists a bus route that satisfies this requirement? Note that a bus route never visits the same place twice. A traffic sign pointing in the direction of the shortest route to Amsterdam is placed at every intersection. You may assume that the input graph is both simple and connected, and that there is a unique optimal route to Amsterdam from every intersection.

Input

• A single line containing two integers: n (2 ≤ n ≤ 105 ), the number of intersections, and m (1 ≤ m ≤ 106 ), the number of undirected roads that connect the intersections. The intersections are numbered from 0 to n − 1. Delft is denoted by intersection i = 0 and Amsterdam is denoted by intersection i = 1.
• m lines that specify the roads – A road is specified by three integers, ai , bi (0 ≤ ai , bi < n and ai 6= bi) and di (0 ≤ di ≤ 500000), where ai and bi are ids of the two intersections that are connected by this road and di is the distance that the bus has to travel to get from ai to bi or vice versa.

Output

As output, give one of the following:
• A path from Delft to Amsterdam that satisfies the requirements, in case such a path exists. – A path is specified by a single line containing an integer k, the length of the path, followed by k integers pi that specify the intersections along the path in the order in which they are crossed, with p0 = 0 and pk−1 = 1.
• The text “impossible”, if such a path does not exist.

Sample

Sample Input 1 
4 5
0 2 5
2 1 5
0 3 10
3 1 20
3 2 5
Sample Output 1
3 0 3 1

Sample Input 2 
4 3
0 1 10
1 2 20
2 3 30
Sample Output 2
impossible

Sample Input 3 
7 9
0 1 800
6 2 300
2 3 75
3 4 80
4 5 50
4 1 100
1 6 35
0 2 120
0 3 100
Sample Output 3
2 0 1

题目描述

现有n个路口,每个路口的路牌都会标记到 1 路口的最短路的下一个节点,现判断从0->1且不能走路牌上标记的方向,是否存在一种答案. 若存在输出路径,否则输出”impossible”.

解题思路

标记源点为1,先用dijkstar标记每个路口的路牌上指明的节点,然后标记的路线不可行,直接dfs爆搜一下标记可行路径.

代码实现

#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int INF=0x3f3f3f3f;
const int maxn = 1e6+7;

int tot;
int dist[maxn],head[maxn],pre[maxn];
bool vis[maxn] , flag;
int ans[maxn],len=0;

struct node
{
    int u;
    int v;
    int c;
    int ne;
} edge[maxn];

struct qnode
{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c) {}
    bool operator <(const qnode &r)const
    {
        return c>r.c;
    }
};

void init()
{
    memset(pre,-1,sizeof(pre));
    memset(vis,0,sizeof(vis));
    memset(dist,INF,sizeof(dist));
    memset(head,-1,sizeof(head));
    tot=0;
    flag=false;
}
void addedge(int u,int v,int cost)
{
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].c=cost;
    edge[tot].ne=head[u];
    head[u]=tot++;
}

void Dijkstra(int n,int start)//点的编号从1开始
{
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
    while(!que.empty())
    {
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])continue;
        vis[u]=true;
        for(int i=head[u];i!=-1;i=edge[i].ne)
        {
            int v=edge[i].v;
            int cost=edge[i].c;
            if(!vis[v] && dist[v]>dist[u]+cost)
            {
                pre[v] = u;
                dist[v] = dist[u]+cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}

void print_ans(int point)
{
    if(point==1)
    {
        cout<<" "<<0;
        return ;
    }
    print_ans(point-1);
    cout<<" "<<ans[point]-1;
}

void dfs(int tmp,int pree)
{
    ans[++len]=tmp;
    vis[tmp]=1;
    if(tmp==2)
    {
        flag=true;
        cout<<len;
        print_ans(len);
        cout<<endl;
        return ;
    }
    for(int i=head[tmp];i!=-1;i=edge[i].ne)
    {
        int v=edge[i].v;
        if(pre[tmp]==v || vis[v]) continue;
        dfs(v,tmp);
        if(flag) return ;
    }
    --len;
}

int main()
{
    IO;
    init();
    int n,m;
    int u,v,c;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v>>c;
        addedge(u+1,v+1,c);
        addedge(v+1,u+1,c);
    }
    Dijkstra(n,2);
    memset(vis,0,sizeof(vis));
    dfs(1,-1);
    if(!flag) cout<<"impossible"<<endl;
    return 0;
}

Ps:Dijkstar 优化算法模板(from kuangbin)

/*
* 使用优先队列优化Dijkstra算法
* 复杂度O(ElogE)
* 注意对vector<Edge>E[MAXN]进行初始化后加边
*/
const int INF=0x3f3f3f3f;
const int MAXN=1000010;
struct qnode
{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c) {}
    bool operator <(const qnode &r)const
    {
        return c>r.c;
    }
};
struct Edge
{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
int dist[MAXN];
void Dijkstra(int n,int start)//点的编号从1开始
{
    memset(vis,false,sizeof(vis));
    for(int i=1; i<=n; i++)dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
    while(!que.empty())
    {
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])continue;
        vis[u]=true;
        for(int i=0; i<E[u].size(); i++)
        {
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dist[v]>dist[u]+cost)
            {
                dist[v]=dist[u]+cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}
void addedge(int u,int v,int w)
{
    E[u].push_back(Edge(v,w));
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值