【BZOJ5470】[FJOI2018]所罗门王的宝藏()

【BZOJ5470】[FJOI2018]所罗门王的宝藏()

题面

BZOJ
洛谷

\(n+m\)个变量,给定\(k\)组限制,每次告诉你\(a_i+b_j=c_k\),问是否有可行解。

题解

一道很呆的题目,我都不知道应该算什么类型了。。。
把行列拆开,对于一个限制\(x,y,c\),连边\(x\)行到\(y\)列,边权为\(c\)
然后\(dfs\)一遍,如果存在环的话显然必须要环上存在合法解,那么随便令一个东西为\(x\),记录每个值为\(ax+b\)的形式,检查二分图是否合法。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 2020
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,m,K;
int a[MAX],b[MAX];bool vis[MAX];
struct Line{int v,next,w;}e[MAX];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
bool Flag;
void dfs(int u)
{
    vis[u]=true;if(!Flag)return;
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v,w=e[i].w;
        if(!vis[v])a[v]=-a[u],b[v]=w-b[u],dfs(v);
        else if(a[v]+a[u]!=0||b[u]+b[v]!=w){Flag=false;return;}
    }
}
int main()
{
    int T=read();
    while(T--)
    {
        n=read();m=read();K=read();cnt=1;
        for(int i=1;i<=K;++i)
        {
            int x=read(),y=read(),d=read();
            Add(x,y+n,d);Add(y+n,x,d);
        }
        Flag=true;
        for(int i=1;Flag&&i<=n;++i)
            if(!vis[i])a[i]=1,b[i]=0,dfs(i);
        puts(Flag?"Yes":"No");
        for(int i=1;i<=n+m;++i)vis[i]=false,h[i]=0;
    }
    return 0;
}

转载于:https://www.cnblogs.com/cjyyb/p/10447085.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值