题解 P3275 【[SCOI2011]糖果】
P3275 [SCOI2011]糖果
题目大意:
求满足 \(k\) 个不等关系的最小正整数解的和。
solution:
这种不等式关系,考虑用差分约束求解。
我们逐一击破每个操作:
设 \(c_i\) 为编号为 \(i\) 的小朋友的糖果数。
- \(c_a=c_b \longrightarrow c_a \geq c_b+0\) 且 \(c_a \geq c_b+0\)。
- $c_a \leq c_b \longrightarrow c_b \geq c_a+1 $。
- \(c_a \geq c_b \longrightarrow c_a \geq c_b+0\)。
- \(c_a > c_b \longrightarrow c_a \geq c_b+1\)。
- \(c_a \leq c_b \longrightarrow c_b \geq c_a+0\)。
按照差分约束连边后跑最长路即可。
细节处理:
- 注意判断无解情况,输出 \(-1\)。
- 结果用 \(\text{long long }\) 保存。
- 源点倒序连接,玄学优化。
- 操作 \(2\) 和 \(4\) 特判自己不能比自己多/少。
代码
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e5+5;
int n,m;
int hd[N],nt[N<<1],to[N<<1],ww[N<<1],cnt;
inline void tian(int x,int y,int z){
to[++cnt]=y,ww[cnt]=z,nt[cnt]=hd[x],hd[x]=cnt;
}
int dis[N],num[N];bool vis[N];
inline bool spfa(){
queue<int> q;
dis[0]=0,vis[0]=1;
q.push(0);
while(q.size()){
int x=q.front();q.pop();
vis[x]=0;
for(int i=hd[x];i;i=nt[i]){
int y=to[i],z=ww[i];
if(dis[y]<dis[x]+z){
dis[y]=dis[x]+z;
if(!vis[y]){
vis[y]=1,num[y]++;
if(num[y]==n+1) return 0;
q.push(y);
}
}
}
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=n;i>=1;i--) tian(0,i,1);//玄学优化
for(int i=1,op,x,y;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);
if(op==1) tian(x,y,0),tian(y,x,0);
else if(op==2) tian(x,y,1);
else if(op==3) tian(y,x,0);
else if(op==4) tian(y,x,1);
else if(op==5) tian(x,y,0);
if(op%2==0&&x==y) return puts("-1"),0;//特判
}
if(!spfa()) return puts("-1"),0;//无解
long long ans=0;
for(int i=1;i<=n;i++) ans+=dis[i];//统计答案
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号