「SCOI2011」糖果

题目描述

幼儿园里有 NNN 个小朋友, lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。
但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候, lxhgww 需要满足小朋友们的 KKK 个要求。
幼儿园的糖果总是有限的, lxhgww 想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

输入格式

输入的第一行是两个整数 NNN , KKK 。
接下来 KKK 行,表示这些点需要满足的关系,每行 333 个数字, xxx , AAA , BBB 。
如果 X=1X=1X=1 .表示第 AAA 个小朋友分到的糖果必须和第 BBB 个小朋友分到的精果一样多。
如果 X=2X=2X=2 ,表示第 AAA 个小朋友分到的糖果必须少于第 BBB 个小朋友分到的糖果。
如果 X=3X=3X=3 ,表示第 AAA 个小朋友分到的糖果必须不少于第 BBB 个小朋友分到的糖果。
如果 X=4X=4X=4 ,表示第 AAA 个小朋友分到的糖果必须多于第 BBB 个小朋友分到的糖果。
如果 X=5X=5X=5 ,表示第 AAA 个小朋友分到的糖果必须不多于第 BBB 个小朋友分到的糖果。

输出格式

输出一行,表示 lxhgww 老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出 −1-11 。

样例

样例输入

5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1

样例输出

11

数据范围与提示

对于 30%30\%30% 的数据,保证 N<100N<100N<100 。
对于 100%100\%100% 的数据,保证 N<100000,K≤100000,1≤X≤5,1≤A,B≤NN < 100000 , K \le 100000 , 1 \le X \le 5 , 1 \le A , B \le NN<100000,K100000,1X5,1A,BN 。


显而易见的差分约束,然后就是各种被卡
首先是在连边的时候要判断是否有同一个点要严格大于或小于自己
然后就是负环的判断,写DFS固然简便,但是会被卡,所以要写BFS,但是还是会被卡
所以这个时候我们有两种选择,第一种是写双端队列的优化,还有一种是反向存边
这也告诉了我们一种思想,在你写SPFA担心被卡的时候,可以采用换连边顺序的方法来优化
同种的还有从两边向中间,先连质数等等   (好像还有莫比乌斯反演之类的神级操作)
反正就是想怎么连就怎么连
最后要注意的就是邻接表一定要开够
下面给出代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
inline int rd(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
inline void write(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}
int n,k;
int head[1000006];
int nxt[2000006],to[2000006];
int total=0;
long long v[2000006];
inline void add(int x,int y,int z){
    total++;
    v[total]=z;
    to[total]=y;
    nxt[total]=head[x];
    head[x]=total;
    return ;
}
long long dis[1000006];
int book[1000006];
int vis[1000006];
int f=0;
int q[1000006];
int l=0,r=0;
inline void spfa(){
    q[++r]=0;
    book[0]=1;
    vis[0]=1;
    while(l<r){
        int h=q[++l];
        book[h]=0;
        for(register int e=head[h];e;e=nxt[e]){
            if(dis[to[e]]<dis[h]+v[e]){
                dis[to[e]]=dis[h]+v[e];
                vis[to[e]]++;
                if(vis[to[e]]>=n){
                    f=1;
                    return ;
                }
                if(!book[to[e]]){
                    q[++r]=to[e];
                    book[to[e]]=1;
                }
            }
        }
    }
    return ;
}
int main(){
    n=rd(),k=rd();
    for(register int i=n;i>=1;i--) add(0,i,1);
    for(register int i=1;i<=k;i++){
        int f=rd(),x=rd(),y=rd();
        if(f==1) add(x,y,0),add(y,x,0);
        if(f==2){
            if(x==y){
                printf("-1");
                return 0;
            }
            add(x,y,1);
        }
        if(f==3) add(y,x,0);
        if(f==4){
            if(x==y){
                printf("-1");
                return 0;
            }
            add(y,x,1);
        }
        if(f==5) add(x,y,0);
    }
    spfa();
    long long ans=0;
    if(f) printf("-1");
    else{
        for(register int i=1;i<=n;i++) ans+=dis[i];
        printf("%lld",ans);
    }
    return 0;
}

 

posted @ 2018-10-07 23:10  Bruce--Wang  阅读(254)  评论(1编辑  收藏  举报