1. 程式人生 > >[luogu P3275] [SCOI2011]糖果

[luogu P3275] [SCOI2011]糖果

blog scoi2011 i++ ons 技術分享 糖果 但是 main empty

[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]糖果