题目在这
题解是这么给的
我们考这样一个有向图对于每个配方建四条边
c->b权值为a ,
c->a 权值为 b
a->c 和 b->c 权值为-1
比如输入的配方是(a, b),能合成c
然后建四条边
c->b 权值为-1
c->a 权值为-1
a->c 权值为 b
b->c 权值为 a
然后做一次bfs 首先把原料都丢进去队列,然后每次到一个点访问它的后
继 如果它和它的权值都是有的那么就丢进去
例如节点 x 能到节点 y 的条件是他们之间的有向边的权值 z 是-1 或者 zx 存在原 料库当中的 这样复杂度大概是 O(N+M)
数据水的情况下我跑了3遍dfs也能过。嗯= = 。
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#define LL long long
#define INF 0x3f3f3f3f
#define MOD 1000000007
const int maxn = 1e5 + 5;
using namespace std;
bool vis[maxn];
bool ok[maxn];
struct node{
int to,cost;
node(){}
node(int to_, int cost_):to(to_),cost(cost_){}
};
vector <node> vec[maxn];
queue <int> que;
void bfs(){
while(!que.empty()){
int u = que.front();
que.pop();
for(int i=0; i<vec[u].size(); i++){
node temp = vec[u][i];
if(temp.cost == -1){//分解
if(!ok[temp.to]){
ok[temp.to] = true;
que.push(temp.to);
vis[temp.to] = true;
}
}
else{
if(vis[temp.cost]){//合成
if(!ok[temp.to]){
que.push(temp.to);
vis[temp.to] = true;
ok[temp.to] = true;
}
}
}
}
}
}
int main(){
int k,n,m,q;
scanf("%d%d%d%d",&k,&n,&m,&q);
memset(vis, false, sizeof(vis));
memset(ok, false, sizeof(ok));
vis[0] = true;
for(int i=0; i<maxn; i++){
vec[i].clear();
}
for(int i=0; i<n; i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
vec[a].push_back(node(c,b));
vec[b].push_back(node(c,a));
vec[c].push_back(node(a,-1));
vec[c].push_back(node(b,-1));
}
for(int i=0; i<m; i++){
int x;
scanf("%d",&x);
vis[x] = true;
que.push(x);
}
bfs();
while(q--){
int x;
scanf("%d",&x);
if(vis[x]) printf("Yes\n");
else printf("No\n");
}
return 0;
}
/*
10 3 4 10
1 2 3
4 5 6
2 5 7
3 4 5 8
1
2
3
4
5
6
7
8
9
10
*/