CSU 2005 Nearest Maintenance Point(最短路+bitset优化转移)

2005: Nearest Maintenance Point
      Time Limit: 2 Sec     Memory Limit: 128 Mb     Submitted: 178     Solved: 15    

Description

A county consists of n cities (labeled 1, 2, …, n) connected by some bidirectional roads. Each road connects a pair of distinct cities. A robot company has built maintenance points in some cities. Now, they need your help to write a program to query the nearest maintenance point to a specific city.

Input

There will be at most 200 test cases. Each case begins with four integers n, m, s, q(2 ≤ n ≤ 104, 1 ≤ m ≤ 5 × 104, 1 ≤ s ≤ min{n, 1000},1 ≤ q ≤ min{n, 1000}), the number of cities, the number of roads, the number of cities which have maintenance points and the number of queries. Then m lines contain the descriptions of roads. Each of them contains three integers ui, vi, wi(1 ≤ ui, vi ≤ n, ui ≠ vi, 1 ≤ wi ≤ 1000), denoting there is a road of length wi which connects city ui and vi. The next line contains s integers, denoting the cities which have maintenance points. Then q lines contain the descriptions of queries. Each of them contains one integer denoting a specific city. The size of the whole input file does not exceed 6MB.

Output

For each query, print the nearest city which has a maintenance point. If there are multiple such cities, print all of them in increasing order separated by a single space. It is guaranteed that there will be at least one such city.

Sample Input

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

Sample Output

3
1
1 3

Hint

Source

湖南省第十三届大学生计算机程序设计竞赛




        比赛的时候MLE到想哭的题目,死都没想到用bitset……
        大致题意:给出一个图,然后给出一些关键点,然后有很多个询问,每次询问的时候问到达某点x最近的关键点是哪一个,如果有多个关键点同样近,那么把这些点全部输出。
        如果不要求全部输出,那就是大水题一道,但现实是要全部输出来。初始的想法,对于每个点设置一个vector,存储到达每个点最近的关键点有哪些。但是发现合并起来并不方便,如果元素较多会导致超时。然后又考虑把最初来源作为新的一维,一起加入优先队列中,作为dijkstra的一种转移状态。然后果断的MLE,然后关于这个MLE的原因又争论了好久……心情变糟,然后GG……
        赛后,听别人一说bitset,然后瞬间感觉自己太菜了……bitset,的每一个位置的0、1恰好可以记录是否从对应位置的点到,然后转移的时候,如果发现多条最短路,只需要利用位运算,把u的bitset状态值或上v的状态值就可以实现快速的转移。最后我在看每一位是0还是1,分别表示是否能从对应位置排名的关键点以最短的距离到达。bitset真的是牛逼……最后,听说有人用set过的,我个人感觉set合并的时候复杂度是玄学,所以当时不敢用,下次还是要试试……具体见代码::
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 10100
using namespace std;

int d[N],m,n,s,q,a[N],ans[N];
typedef pair<int,int> P;
struct Edge{int y,w;};
vector<Edge> g[N];
bitset<1010> p[N];					//最多1000个关键点,用关键点的序号来对应每一位

inline void dijkstra()
{
    priority_queue<P,vector<P>,greater<P> > q;
    for(int i=1;i<=n;i++)
    {d[i]=INF;p[i].reset();}
    for(int i=1;i<=s;i++)				//初始时多个起点,并赋值好bitset的状态
    {
        q.push(P{0,a[i]});
        p[a[i]][i]=1; d[a[i]]=0;
    }
    while (!q.empty())
    {
        int w=q.top().first;
        int j=q.top().second;
        q.pop(); if (w>d[j]) continue;
        for(int k=0;k<g[j].size();k++)
        {
            int y=g[j][k].y;
            int dist=w+g[j][k].w;
            if (d[y]>dist)
            {
                d[y]=dist; p[y]=p[j];			//如果是大于,那么直接赋值覆盖原来的
                q.push(P(d[y],y));
            } else if (d[y]==dist) p[y]|=p[j];		//如果相等,那么用或来继承状态
        }
    }
}

int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&s,&q))
    {
        memset(g,0,sizeof(g));
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            g[u].push_back(Edge{v,w});
            g[v].push_back(Edge{u,w});
        }
        for(int i=1;i<=s;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+1+s);				//要求关键点升序输出
        dijkstra();
        while(q--)
        {
            int x,tot=0; scanf("%d",&x);
            for(int i=1;i<=s;i++)
                if (p[x][i]) ans[++tot]=a[i];		//判断对应位置是否能以最短路到达
            for(int i=1;i<tot;i++)
                printf("%d ",ans[i]);
            printf("%d\n",ans[tot]);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值