P3275 [SCOI2011]糖果

传送门

显然的差分约束

要求最小值

那就要用 ≥ 号来表示每个小朋友之间的关系

边 ( u,v ) 的权值 x 表示 u 小朋友要比 v 小朋友多 x 个糖

然后跑最长路

如果有正环说明无法满足所有人的要求(A比B多,B比C多,C又要比A多这样的环)

然后因为毒瘤的数据

1.要特判一波小朋友的无理要求(自己的糖要比自己少什么的...)

2.建一个虚节点,连接每个小朋友时从 n 到 1 连(不然会T...)

然后注意每个小朋友至少要一个糖

所以虚节点连接小朋友时权值要为1

最后答案就是每个小朋友的 dis 值之和(每个小朋友的 dis 表示 ta 最少要多少个糖)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
inline int read()
{
    int x=0; char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return x;
}
const int N=1e6+7;
int n,m;
int fir[N],from[N],to[N],val[N],cnt;
inline void add(int a,int b,int c)
{
    from[++cnt]=fir[a];
    fir[a]=cnt; to[cnt]=b; val[cnt]=c;
}

//SPFA模板
int dis[N],tot[N];//tot记录一个点进入队列的次数,如果大于节点总数说明有正环
bool vis[N],flag;
queue <int> q;
void SPFA()
{
    q.push(0); dis[0]=0; vis[0]=1;
    while(!q.empty())
    {
        int u=q.front(); q.pop(); vis[u]=0;
        if(++tot[u]>=n) { flag=1; break; }
        for(int i=fir[u];i;i=from[i])
        {
            int &v=to[i];
            if(dis[v]<dis[u]+val[i])
            {
                dis[v]=dis[u]+val[i];
                if(!vis[v]) q.push(v),vis[v]=1;
            }
        }
    }
}

int main()
{
    int a,b,c;
    n=read(); m=read();
    for(int i=1;i<=m;i++)
    {
        a=read(); b=read(); c=read();
        if(a==1) add(b,c,0),add(c,b,0);
        if(a==2)
        {
            if(b==c) { flag=1; break; }//特判一波小朋友的无理要求
            add(b,c,1);
        }
        if(a==3) add(c,b,0);
        if(a==4)
        {
            if(b==c) { flag=1; break; }
            add(c,b,1);
        }
        if(a==5) add(b,c,0);
    }
    for(int i=n;i;i--) add(0,i,1);//for要从n到1,毒瘤数据...
    if(flag) { cout<<-1; return 0; }

    SPFA();

    if(flag) { cout<<-1; return 0; }
    long long ans=0;//ans要用long long 存
    for(int i=1;i<=n;i++) ans+=dis[i];
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-09-26 09:47  LLTYYC  阅读(133)  评论(0编辑  收藏  举报