2015-2016 Samara Regional Intercollegiate Programming Contest G - Short Path 【好题】


G. Short Path


time limit per test  2.0 s

memory limit per test      256MB


In my opinion, people are divided into two categories: some livein the future while others — in the past. Should it be explained whatcategory did I belong? The mystery I hunted for a half of my life, finally wastaking shape. Good Magician didn't know where Dragon hid. But he knew thatbandit dens in some cities of the kingdom were controlled by people from theDragon's gang. For each city he gave me a reliable information, whether Dragoncontrolled that city or not.

I was staring on the map of Fairy Kingdom trying to understandwhere to go now. There were n cities in the Kingdom, connected by m roads, with the length of the j-th road equal to wj. I guessed that Dragon hid in one of two cities controlled byhis gang with the shortest path between them. First of all, the traffic of BlueTea was the highest between them, and secondly, in case of emergency it waspossible to move quickly from one of the cities to the other. All that remainedwas just to find such pair of cities.

Input

The first line contains two integers separated by a space: n and m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105) — the number ofcities in Fairy Kingdom and the number of roads between them, correspondingly.

The second line contains n integers separated by spaces. On the i-th position the number 1 is written, if the i-th city is under control of Dragon'sgang; otherwise the number 0 is written there.

The next m lines contain three integers each, separated by spaces: ai, bi, wi (1 ≤ ai < bi ≤ n, 1 ≤ wi ≤ 109) — the numbers ofcities connected by a road and the length of this road. The cities are numberedfrom 1. Each pair of cities is presented at most once.

Output

In the first line output a single integer — the length ofthe shortest path between cities where Dragon presumably hides.

In the second line output two integers separated by aspace — the numbers of these cities.

Ifthere are several possible answers, output any of them. If no two citiescontrolled by Dragon's people have a path between them, output «No luck at all» without quotes.

Examples

Input

4 4
1 0 0 1
1 2 1
1 3 2
2 4 3
3 4 1

Output

3
4 1

Input

7 9
1 0 1 1 0 0 1
1 2 5
1 4 100
2 3 5
2 5 4
2 6 4
3 7 100
4 5 2
6 7 2
5 6 3

Output

7
4 7

Input

2 1
0 0
1 2 1

Output

No luck at all

 


【题意】


给出n个城市和它们之间的m条道路,且每个城市有一个编号:0或1。问所有编号为1的城市间的最短距离为多少。若不存在输出No luck at all。


【思路】


我们设dis[i]表示城市i到一个编号为1的城市(包括自身)的最短距离,先把编号为1的点分成一类,然后我们初始化他们的dis为0,然后利用SPFA进行松弛操作,但这里我们比平常的SPFA多记录一个信息pre[i],即取到城市i到编号为1的城市(包括自身)的最短距离的那个城市的编号。


接着我们去考虑枚举每条道路的情况,显然一共有三种不同的情况。


  1. 两个城市的编号都是1,那么他们之间的距离可以满足题目要求。(再加边距离一定变大)

  2. 一个城市的编号为1,另一个为0,为了满足题目要求,我们需要把编号为0的那个城市连接到一个最近的城市,那么总距离为这条道路的长度+最短距离。

  3. 两个城市编号都为0,那么我们需要把两个点都连接到距离最近的城市,总距离为这条道路的长度+两个最短距离。


枚举边的同时更新最小值即可。


#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T,scanf("%d",&T),while(T--)

typedef long long ll;
const int maxn = 100005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;

int n,m,cnt;
int a[maxn];
ll dis[maxn];
int head[maxn];
int vis[maxn];
int pre[maxn];

struct node
{
    int u,v,next;
    ll w;
}e[maxn*2];

void add(int u,int v,ll w)
{
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

void spfa()
{
    mst(dis,0x3f);
    queue<int>q;
    for(int i=1;i<=n;i++)
    {
        if(a[i])
        {
            q.push(i);
            vis[i]=1;
            dis[i]=0;
            pre[i]=i;
        }
    }
    while(q.size())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v;
            ll w=e[i].w;
            if(dis[u]+w<dis[v])
            {
                dis[v]=dis[u]+w;
                pre[v]=pre[u];
                if(vis[v]==0)
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    mst(head,-1);
    mst(vis,0);
    cnt=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=0;i<m;i++)
    {
        int u,v;
        ll w;
        scanf("%d%d%I64d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    spfa();
    ll ans=(ll)INF*INF;
    int ans1,ans2;
    for(int i=0;i<cnt;i+=2)
    {
        int u=e[i].u;
        int v=e[i].v;
        if(a[u]&&a[v])
        {
            if(e[i].w<ans)
            {
                ans=e[i].w;
                ans1=u;
                ans2=v;
            }
        }
        else if(a[u])
        {
            if(pre[v]!=u&&e[i].w+dis[v]<ans)
            {
                ans=e[i].w+dis[v];
                ans1=u;
                ans2=pre[v];
            }
        }
        else if(a[v])
        {
            if(pre[u]!=v&&e[i].w+dis[u]<ans)
            {
                ans=e[i].w+dis[u];
                ans1=pre[u];
                ans2=v;
            }
        }
        else
        {
            if(pre[u]!=pre[v]&&e[i].w+dis[u]+dis[v]<ans)
            {
                ans=e[i].w+dis[u]+dis[v];
                ans1=pre[u];
                ans2=pre[v];
            }
        }
    }
    if(ans==(ll)INF*INF)
    {
        puts("No luck at all");
    }
    else printf("%I64d\n%d %d\n",ans,ans1,ans2);
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值