链接:https://www.nowcoder.net/acm/contest/78/I
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
有机合成是指从较简单的化合物或单质经化学反应合成有机物的过程。
有时也包括从复杂原料降解为较简单化合物的过程。
由于有机化合物的各种特点,尤其是碳与碳之间以共价键相连,有机合成比较困难,常常要用加热、光照、加催化剂、加有机溶剂甚至加压等反应条件。
但是前人为有机合成提供了许多宝贵的经验。
现在已知有K总物质和N个前人已经总结出的合成反应方程式
小星想知道在现有M种物质的情况下 能否合成某些物质。
输入描述:
第一行输入四个整数 K,N,M,Q(K,N,M,Q<=1e5)
K表示一共K总物质
接下来N行 每行三个数字a b c(任意两个数可能相等)
表示a和b反应可以生成c 反应是可逆的
即可以通过c可以分解出a和b
接下来一行行然后输入m个数,表示m种原料(每一种原料都可以认为有无限多)
接下来Q个行Q个询问
对于每个询问
输出一个数字 x 判断是否可以通过一些反应得到第 x
输出描述:
可以得到Yes否则No
示例1
输入
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
输出
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
No
No
说明
一共10总物质有第3,4,5,8 四种原料
查询每一种是否可以通过反应得到
首先通过3可以分解得到1 2
然后4 5合成6
2 5合成7
于是除了9 10都可以得到
暴力代码.
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e5+11;
const int mod = 7653;
const int inf = 0x3f3f3f3f;
const double E = exp(1.0);
struct Node{
int a,b,c;
}node[N];
bool ok[N];
int main(){
int k,n,m,q; scanf("%d%d%d%d",&k,&n,&m,&q);
for(int i=1;i<=n;i++) scanf("%d%d%d",&node[i].a,&node[i].b,&node[i].c);
for(int i=1;i<=m;i++){
int zs; scanf("%d",&zs);
ok[zs]=1;
}
int num=100;
while(num--){
for(int i=1;i<=n;i++){
Node t=node[i];
if(ok[t.a]&&ok[t.b]) ok[t.c]=1;
if(ok[t.c]) ok[t.a]=ok[t.b]=1;
}
}
while(q--){
int x; scanf("%d",&x);
if(ok[x]) puts("Yes");
else puts("No");
}
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
*/
代码二 BFS
对于 a b 合成 c
我们建立边
a c b
b c a
c a -1
c b -1
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e5+11;
const int M = 3e6;
const int mod = 7653;
const int inf = 0x3f3f3f3f;
const double E = exp(1.0);
struct Edge{
int from,to,val,next;
}edge[M];
int head[N],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,int c){
Edge e={a,b,c,head[a]};
edge[top]=e; head[a]=top++;
}
bool ok[N];
queue<int>Q;
int main(){
init();
int k,n,m,q;scanf("%d%d%d%d",&k,&n,&m,&q);
for(int i=1;i<=n;i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
addedge(a,c,b);
addedge(b,c,a);
addedge(c,a,-1);
addedge(c,b,-1);
}
for(int i=1;i<=m;i++){
int z;scanf("%d",&z);
Q.push(z); ok[z]=1;
}
while(!Q.empty()){
int now=Q.front(); Q.pop();
for(int i=head[now];i!=-1;i=edge[i].next){
Edge e=edge[i];
if(ok[e.to]) continue; // 每个点只访问一遍
if(e.val==-1 || ok[e.val]) {// val==-1代表分解,后一个代表合成情况 .
ok[e.to]=1;
Q.push(e.to);
}
}
}
while(q--){
int x;scanf("%d",&x);
if(ok[x]) puts("Yes");
else puts("No");
}
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
*/