[luogu P3275] [SCOI2011]糖果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu P3275] [SCOI2011]糖果相关的知识,希望对你有一定的参考价值。

[luogu P3275] [SCOI2011]糖果

题目描述

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

输入输出格式

输入格式:

 

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
输出样例#1:
11

说明

【数据范围】

对于30%的数据,保证 N<=100

对于100%的数据,保证 N<=100000

对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N

 

也是一道容易看出来的差分题。

但是这题点数和边数都在1e5的级别,还要判正环,spfa极其容易被卡掉。。但是本蒟蒻只会spfa判正环,怎么办??

交了好几发,TLE80,TLE90,怎么卡都卡不过去。。

后来%了某些dalao的code,加了两个特判,然后加了一个奇奇怪怪的剪枝(直接把所有点push,而不是建超级源),然后就A掉了。

更奇怪的是,我发现两个特判加上只能90分,有了后面的剪枝就100了,而且原来T的点跑得飞快。。。

真是令人百思不得其解(竟然快了这么多。。)

说到卡时间,还要%一下zzydalao。。

code:

技术分享
 1 %:pragma GCC optimize(2)
 2 #include<bits/stdc++.h>
 3 #define LL long long
 4 #define RI register int
 5 #define Ms(a,x) memset(a,x,sizeof a)
 6 using namespace std;
 7 const int N=100005,M=300005;
 8 int n,m,inf,tot; bool vis[N];
 9 int lnk[N],nxt[M],son[M],w[M],f[N],dis[N];
10 queue <int> Q;
11 inline int read() {
12     int x=0,f=1; char ch=getchar();
13     while (ch<0||ch>9) f=(ch==-)?-1:1,ch=getchar();
14     while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
15     return x*f;
16 }
17 void add(int x,int y,int z) {
18     nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y,w[tot]=z;
19 }
20 bool spfa() {
21     for (RI x; !Q.empty(); ) {
22         x=Q.front(),Q.pop(),vis[x]=0;
23         for (RI j=lnk[x],y; j; j=nxt[j])
24             if (dis[y=son[j]]<dis[x]+w[j]) {
25                 dis[y]=dis[x]+w[j];
26                 if (++f[y]>n) return 0;
27                 if (!vis[y]) vis[y]=1,Q.push(y);
28             }
29     }
30     return 1;
31 }
32 int main() {
33     n=read(),m=read();
34     for (int i=1; i<=n; i++) dis[i]=f[i]=vis[i]=1,Q.push(i);
35     for (int i=1,x,y,z; i<=m; i++) {
36         z=read(),x=read(),y=read();
37         switch (z) {
38             case 1:add(x,y,0),add(y,x,0); break;
39             case 2:if (x==y) {puts("-1"); return 0;} add(x,y,1); break;
40             case 3:add(y,x,0); break;
41             case 4:if (x==y) {puts("-1"); return 0;} add(y,x,1); break;
42             case 5:add(x,y,0); break;
43         }
44     }
45     LL ans=0;
46     if (!spfa()) ans=-1; else
47     for (RI i=1; i<=n; i++) ans+=dis[i];
48     cout<<ans<<\n;
49     return 0;
50 }
View Code

 

以上是关于[luogu P3275] [SCOI2011]糖果的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3275 [SCOI2011]糖果

P3275 [SCOI2011]糖果

洛谷P3275 [SCOI2011]糖果

P3275 [SCOI2011]糖果

P3275 [SCOI2011]糖果

P3275 [SCOI2011]糖果