您的位置:首页 > 其它

【常州大学新生寒假训练会试】 合成反应 【BFS or 暴力】

2018-02-07 21:38 295 查看
链接: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
;
bool ok
;
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
,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
;
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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: