「SCOI2011」糖果
Posted greed-vi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「SCOI2011」糖果相关的知识,希望对你有一定的参考价值。
蒟蒻又回来写题解了。。。
题面
幼儿园里有 N 个小朋友, lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。
但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候, lxhgww 需要满足小朋友们的 K 个要求。
幼儿园的糖果总是有限的, lxhgww 想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入格式
输入的第一行是两个整数 N, K 。
接下来 K 行,表示这些点需要满足的关系,每行 33 个数字, 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。
思路
神仙题(不是思路,而是卡时神仙。。。)
不过还是先看思路。。。
由x==1时可得A==B,就是两边相等,建一条a到b权为0的双向边。
由x==2时可得A<B,所以要让A+x(x>=1)>B,建一条a到b权为1的单向边。
由x==3时可得A>=B,所以要让B+x(x>=0)>=A,建一条b到a权为0的单向边。
由x==4时可得A>B,所以要让B+x(x>=1)>A,建一条b到a权为1的单向边。
由x==5时可得A<=B,所以要让A+x(x>=0)>=B,建一条a到b权为0的单向边。
然后根据不等式同大取大,跑个SPFA最长路(顺便判个环)就行了(然后没A)。
???
万一x==2||x==4时A==B呢?你还要再跑一遍???直接特判cout<<-1<<endl;return 0;
万一爆int呢?开long long吧
万一。。。这个真没想到。。。
先看一下90分代码
// luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; struct node{long long dis,to,next;}Edge[1000005]; long long head[1000005],cnt=0,N,K; bool vis[1000005]; long long dis[1000005],tot[1000005]; inline long long read() { int ret=0,f=1;char ch=getchar(); while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-f;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) ret=ret*10+ch-‘0‘,ch=getchar(); return ret*f; } void add(long long a,long long b,long long c) { Edge[++cnt].next=head[a]; Edge[cnt].to=b; Edge[cnt].dis=c; head[a]=cnt; } void SPFA(long long s) { for (long long i=1;i<=N;i++) vis[i]=0,dis[i]=-2e9,tot[i]=0; queue<int> q; q.push(s); vis[s]=1; dis[s]=0; tot[s]++; while(!q.empty()) { long long u=q.front(); q.pop(); vis[u]=0; for (long long i=head[u];i;i=Edge[i].next) { long long v=Edge[i].to; if (dis[v]<dis[u]+Edge[i].dis) { dis[v]=dis[u]+Edge[i].dis; if (!vis[v]&&tot[v]<N) tot[v]++,q.push(v),vis[v]=0; else if (tot[v]>=N) { cout<<-1<<endl; exit(0); return; } } } } } int main() { N=read();K=read(); for (long long i=1;i<=K;i++) { long long X,A,B; X=read();A=read();B=read(); if (X==1) add(A,B,0),add(B,A,0); if (X==2) if (A==B) {cout<<-1<<endl;return 0;} else add(A,B,1); if (X==3) add(B,A,0); if (X==4) if (A==B) {cout<<-1<<endl;return 0;} else add(B,A,1); if (X==5) add(A,B,0); } long long s=0; for (long long i=1;i<=N;i++) add(s,i,1); SPFA(s); long long ans=0; for (long long i=1;i<=N;i++) ans+=dis[i]; cout<<ans<<endl; return 0; }
再看一下100代码
#include<bits/stdc++.h> using namespace std; struct node{long long dis,to,next;}Edge[1000005]; long long head[1000005],cnt=0,N,K; bool vis[1000005]; long long dis[1000005],tot[1000005]; inline long long read() { int ret=0,f=1;char ch=getchar(); while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-f;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) ret=ret*10+ch-‘0‘,ch=getchar(); return ret*f; } void add(long long a,long long b,long long c) { Edge[++cnt].next=head[a]; Edge[cnt].to=b; Edge[cnt].dis=c; head[a]=cnt; } void SPFA(long long s) { for (long long i=1;i<=N;i++) vis[i]=0,dis[i]=-1,tot[i]=0; queue<long long> q; q.push(s); vis[s]=1; dis[s]=0; tot[s]++; while(!q.empty()) { long long u=q.front(); q.pop(); vis[u]=0; for (long long i=head[u];i;i=Edge[i].next) { long long v=Edge[i].to; if (dis[v]<dis[u]+Edge[i].dis) { dis[v]=dis[u]+Edge[i].dis; if (!vis[v]&&tot[v]<N) tot[v]++,q.push(v),vis[v]=0; else if (tot[v]>=N) { cout<<-1<<endl; exit(0); return; } } } } } int main() { N=read();K=read(); for (long long i=1;i<=K;i++) { long long X,A,B; X=read();A=read();B=read(); if (X==1) add(A,B,0),add(B,A,0); if (X==2) { if (A==B) {cout<<-1<<endl;return 0;} else add(A,B,1); } if (X==3) add(B,A,0); if (X==4) { if (A==B) {cout<<-1<<endl;return 0;} else add(B,A,1); } if (X==5) add(A,B,0); } long long s=0; for (long long i=N;i>=1;i--) add(s,i,1);//神仙优化,看到就是赚到 SPFA(s); long long ans=0; for (long long i=1;i<=N;i++) ans+=dis[i]; cout<<ans<<endl; return 0; }
。。。等待dalao解答
以上是关于「SCOI2011」糖果的主要内容,如果未能解决你的问题,请参考以下文章