[BZOJ2330/Luogu3275][SCOI2011]糖果

题目链接:

BZOJ2330

Luogu3275

明显的一个差分约束模型。

\(C_i\)表示小朋友\(i\)有的糖果数,那么有如下连边方式:

  • \(X=1\)

    • 因为\(C_A=C_B\),有\(C_A\ge C_B+0,C_B\ge C_A+0\),连边\((A,B,0),(B,A,0)\)
  • \(X=2\)

    • 因为\(C_A<C_B\),有\(C_B\ge C_A+1\),连边\((A,B,1)\)

那么同理:

  • \(X=3\),连边\((B,A,0)\)

  • \(X=4\),连边\((B,A,1)\)

  • \(X=5\),连边\((A,B,0)\)

需要注意,若\(X\in\{2,4\}\)\(A\not=B\),则无解。

然后判正环即可。

最后的答案?

因为每个人都要有糖,将所有节点初始距离设为\(1\),跑一遍最长路即为答案。

时间复杂度 \(O(nk)\)

#include <queue>
#include <cstdio>
 
int n,k;
int Head[100005],Next[200005],Val[200005],To[200005],En;
int Cnt[100005],Dis[100005];
bool v[100005];
std::queue<int> q;
 
void Add(int x,int y,int z)
{
    Next[++En]=Head[x];
    Head[x]=En;
    To[En]=y;
    Val[En]=z;
}
 
bool SPFA()
{
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        v[x]=0;
        for(int i=Head[x];i;i=Next[i])
        {
            int y=To[i];
            if(Dis[y]<Dis[x]+Val[i])
            {
                Dis[y]=Dis[x]+Val[i];
                if(++Cnt[y]==n)return false;
                if(!v[y])v[y]=1,q.push(y);
            }
        }
    }
    return true;
}
 
int main()
{
    scanf("%d%d",&n,&k);
    while(k--)
    {
        int op,a,b;
        scanf("%d%d%d",&op,&a,&b);
        if(op==1)Add(a,b,0),Add(b,a,0);
        else if(op==2)Add(a,b,1);
        else if(op==3)Add(b,a,0);
        else if(op==4)Add(b,a,1);
        else Add(a,b,0);
        if(!(op&1)&&a==b)return puts("-1"),0;
    }
    for(int i=1;i<=n;++i)v[i]=Dis[i]=1,q.push(i);
    if(!SPFA())return puts("-1"),0;
    long long Ans=0;
    for(int i=1;i<=n;++i)Ans+=Dis[i];
    return printf("%lld\n",Ans),0;
}
posted @ 2018-12-23 21:37  LanrTabe  阅读(141)  评论(0编辑  收藏  举报