常州大学新生赛 I-合成反应

链接: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都可以得到

思路:存边的时侯用(a, b, c)代表a需要在b存在时能到达c,b为0则不需要额外条件,建图完毕。bfs时若遍历到a需要借助b到达c但b还没出现的情况,则将c加入到set[b]/vector[b]里,在之后如果b
诞生时,则将b集合里的所有元素都诞生出。时空复杂度都是线性。
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <iomanip>
#include <cctype>
#include <cassert>
#include <bitset>
#include <ctime>

using namespace std;

#define pau system("pause")
#define ll long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
#define clr(a, x) memset(a, x, sizeof(a))

const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

int k, n, m, q;
struct edge {
    int b, v;
    edge () {}
    edge (int b, int v) : b(b), v(v) {}
};
vector<edge> E[100015];
set<int> ss[100015];
queue<int> que;
bool vis[100015], exist[100015];
void born(int x) {
    if (exist[x]) {
        return;
    }
    exist[x] = 1;
    que.push(x);
    for (set<int>::iterator it = ss[x].begin(); it != ss[x].end(); ++it) {
        int y = *it;
        born(y);
    }
    ss[x].clear();
}
int main() {
    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);
        E[a].pb(edge(b, c));
        E[b].pb(edge(a, c));
        E[c].pb(edge(0, a));
        E[c].pb(edge(0, b));
    }
    for (int i = 1; i <= m; ++i) {
        int x;
        scanf("%d", &x);
        que.push(x);
        exist[x] = 1;
    }
    while (que.size()) {
        int x = que.front(); que.pop();
        if (vis[x]) continue;
        vis[x] = 1;
        for (int i = 0; i < E[x].size(); ++i) {
            int b = E[x][i].b;
            int v = E[x][i].v;
            if (!b) {
                born(v);
            } else {
                if (exist[b]) {
                    born(v);
                } else {
                    if (!exist[v]) {
                        ss[b].insert(v);
                    }
                }
            }
        }
    }
    while (q--) {
        int x;
        scanf("%d", &x);
        puts(exist[x] ? "Yes" : "No");
    }
    return 0;
}

 

posted @ 2018-02-07 20:11  hit_yjl  阅读(143)  评论(0编辑  收藏  举报