zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    freak out用法
    kinda用法
    比较级与最高级
    issue用法
    invite用法
    yet用法
    follow用法
    get用法
    turn up&turn off&turn on用法
    关于document.lastModified属性
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9705138.html
Copyright © 2011-2022 走看看