常州大学新生寒假训练会试 I-合成反应(bfs)

题目在这
题解是这么给的

我们考这样一个有向图对于每个配方建四条边
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
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值