http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2005
题意:
给你一张图,包含点,边,边权值。给定一些点为维修站,问你离每个点最近的维修站是哪【些】点。
多个答案按上升排序
POINT:
把所有维修站连上一个超级汇点0,然后从0开始跑最短路。
用biset状态压缩来存当前点最近的一个维修站。首先把所有维修站都记录一个bitset,即他本身,然后开始更新。
注意状态转移的这个细节。
我有超级汇点,但是他的状态是0,所以当超级汇点跑到维修站时不能更新bitset状态
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<bitset>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1e4+44;
const int inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
vector<int>G[maxn];
vector<int>W[maxn];
bitset<maxn> cnt[maxn];
int n,m,s,q;
void dij()
{
int dis[maxn];
for(int i=0;i<=n;i++) dis[i]=inf;
dis[0]=0;
priority_queue<pii,vector<pii>,greater<pii> > q;
q.push(make_pair(0,0));
while(!q.empty()){
pii tu = q.top();
q.pop();
int now=tu.first;
int u=tu.second;
if(now>dis[u]) continue;
for(int i=0;i<G[u].size();i++){
int w=W[u][i];
int v=G[u][i];
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(u!=0){
cnt[v]=cnt[u];
}
q.push(make_pair(dis[v],v));
}else if(dis[v]==dis[u]+w){
cnt[v]|=cnt[u];
}
}
}
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&s,&q)){
for(int i=0;i<=n;i++){
G[i].clear();
W[i].clear();
cnt[i].reset();
}
for(int i=1;i<=m;i++){
int u,v,w;scanf("%d%d%d",&u,&v,&w);
G[u].push_back(v);
W[u].push_back(w);
G[v].push_back(u);
W[v].push_back(w);
}
for(int i=1;i<=s;i++){
int x;
scanf("%d",&x);
cnt[x].set(x);
G[0].push_back(x);
W[0].push_back(0);
}
dij();
while(q--){
int x;scanf("%d",&x);
int p=0;
for(int i=1;i<=n;i++){
if(cnt[x][i]==1){
if(p) printf(" ");
printf("%d",i);
p++;
}
}
printf("\n");
}
}
return 0;
}