|BZOJ 2330|差分约束|[SCOI2011]糖果

BZOJ传送门
差分约束。
裸题不讲了。可以看我的差分约束学习笔记。
注意这题直接把所有点加进来做,否则TLE,还要开long long

#include<cstdio>  
#include<algorithm>  
#include<cstring>  
#include<vector>
#include<queue>
#define ms(i,j) memset(i,j, sizeof i);
#define ll long long
using namespace std;
const int MAXN = 100000 + 5; 
ll n,k;
struct edge
{
    ll u,v,c;
}E[MAXN*4];
ll e_num = 0;
vector<ll> G[MAXN];
void addE(ll u, ll v, ll c)
{
    e_num++;
    E[e_num].u = u;
    E[e_num].v = v;
    E[e_num].c = c;
    G[u].push_back(e_num);
}
ll dis[MAXN];
ll vi[MAXN];
ll cir[MAXN];
ll spfa()
{
    queue<ll> q;
    for (ll i=1;i<=n;i++)
    {
        dis[i] = 1;
        vi[i] = false;
        cir[i] = 1;
        q.push(i);
    }
    while (!q.empty())
    {
        ll r = q.front(); q.pop();
        for (ll i=0;i<G[r].size();i++)
        {
            edge ed = E[G[r][i]];
            vi[ed.v] = false;
            if (dis[ed.v]<dis[r]+ed.c)
            {
                dis[ed.v] = dis[r]+ed.c;
                if (!vi[ed.v])
                {
                    cir[i]++;
                    if (cir[i]>n)
                    {
                        return false;
                    }
                    vi[ed.v] = true;
                    q.push(ed.v);
                }
            }
        }
    }
    return true;
}
int main()  
{  
    scanf("%d%d", &n, &k);
    for (ll i=1;i<=k;i++)
    {
        ll x,a,b;
        scanf("%lld%lld%lld", &x, &a, &b);
        switch(x)
        {
            case 1: addE(a,b,0); addE(b,a,0); break;
            case 2: if (a==b) {printf("-1\n");return 0;} addE(a,b,1); break;
            case 3: addE(b,a,0); break;
            case 4: if (a==b) {printf("-1\n");return 0;} addE(b,a,1); break;
            case 5: addE(a,b,0); break;
        }
    } 
    if(!spfa()) printf("-1\n"); else 
        {
            ll ans = 0;
            for (ll i=1;i<=n;i++)
            {
                ans += dis[i];
            }
            printf("%lld\n", ans);
        }   
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值