记录一下codeforces第一次独立写出来1800分的题目

题目链接:https://codeforces.com/contest/1850/problem/H

题目的意思是给你n个人,与m对关系,根据这些关系来计算出是否能全部满足。

题目很好想,把这些人看成点,然后距离是权值,开了一个vector<pair<int,int>> g[N]来存储节点与值,因此可以看成一个森林,因为数轴上的点可以看成是无穷的,只要把遍历最开始的那个人的为之前看成0即可实现。

直接看代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N = 2e5;

int d[N];//度
int vi[N];//第i个点是否访问
int wi[N],ans[N];//wi[i]第i个节点当前的权值,ans[i]是这个点是否满足重复的

vector<pair<int,int>> g[N];//存边与权值,一个正权值一个负权值

void dfs(int now,int root,int w){//分别存储当前节点,父节点,父节点权值
    for(auto [y,wn]:g[now]){
        if(y==root)continue;
        int k=w+wn;
        if(vi[y]){//如果这个点被访问过
            if(wi[y]!=k)ans[y]=1;//如果两次权值计算结果不相同那么就不对
            continue;//遍历过了就说明他的孩子也遍历过了
        }
        vi[y]=1;//已经访问
        wi[y]=k;//给予权值
        dfs(y,now,k);//递归
    }
}

void ChiefNing()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        g[i].clear();
        d[i]=0;
        vi[i]=0;
        wi[i]=0;
        ans[i]=0;
    }
    for(int i=0;i<m;i++){
        int x,y,w;
        cin>>x>>y>>w;
        g[x].push_back({y,w});//x->y存正权值
        g[y].push_back({x,-w});//y->x存负权值
        d[x]++;
        d[y]++;
    }
    for(int i=1;i<=n;i++){
        if(vi[i])continue;//访问过了
        vi[i]=1;
        dfs(i,i,0);
        wi[i]=0;
    }
    for(int i=1;i<=n;i++){
        if(ans[i]==1){
            cout<<"NO"<<endl;
            return ;
        }
    }
    cout<<"YES"<<endl;
}

signed main(void)
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int _;
    cin>>_;
    while(_--)
        ChiefNing();
    return 0;
}

比较清楚,不多说了,大致意思是如果有一个c点,从a点和b点都可以到达c点,并且a和b点有值(已经访问),根据a,b两点来计算c的权值,如果不相等那么就设置为1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值