P3275 [SCOI2011] 糖果(差分约束)
P3275 [SCOI2011] 糖果
题目描述
幼儿园里有
输入格式
输入的第一行是两个整数
- 如果
, 表示第 个小朋友分到的糖果必须和第 个小朋友分到的糖果一样多; - 如果
, 表示第 个小朋友分到的糖果必须少于第 个小朋友分到的糖果; - 如果
, 表示第 个小朋友分到的糖果必须不少于第 个小朋友分到的糖果; - 如果
, 表示第 个小朋友分到的糖果必须多于第 个小朋友分到的糖果; - 如果
, 表示第 个小朋友分到的糖果必须不多于第 个小朋友分到的糖果;
输出格式
输出一行,表示
输入输出样例 #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
说明/提示
对于
对于
对于所有的数据,保证
这道题是一道典型的差分约束题,由于图不一定是连通的,所以我们需要建一个零点使他与所有点连接,边权为零,其次对于x=2和x=4时a和b肯定不能相等,所以我们可以在输入时就能直接得出答案,这样可以减少计算量,但我还是不能通过全部的hack
#include<iostream>
#include<queue>
#include<vector>
#define int long long
using namespace std;
char* p1, * p2, buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x = 0, f = 1;
char ch = nc();
while (ch < 48 || ch>57)
{
if (ch == '-')
f = -1;
ch = nc();
}
while (ch >= 48 && ch <= 57)
x = x * 10 + ch - 48, ch = nc();
return x * f;
}
const int N=1e6+10;
struct node{
int id,dis;
};
int cnt[N];
int vis[N];
vector<node>vc[N];
int w[N];
int n,k;
void spfa(){
queue<int>q;
for(int i=1;i<=n;i++){
vc[0].push_back({i,0});
}
for(int i=0;i<=n;i++)w[i]=1e9;
w[0]=0;
for(int i=0;i<=n;i++)q.push(i),vis[i]=1;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=0;i<vc[u].size();i++){
int v=vc[u][i].id;
if(w[u]+vc[u][i].dis<w[v]){
w[v]=w[u]+vc[u][i].dis;
cnt[v]=cnt[u]+1;
if(cnt[v]>=n+1){
cout<<"-1";
return;
}
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
int sum=0;
for(int i=1;i<=n;i++)sum+=-w[i];
cout<<sum+n;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
while(k--){
int x,a,b;
cin>>x>>a>>b;
if(x==1)vc[a].push_back({b,0}),vc[b].push_back({a,0});
if(x==2){
if(a==b){
cout<<"-1";
return 0;
}
vc[a].push_back({b,-1});
}
if(x==3)vc[b].push_back({a,0});
if(x==4){
if(a==b){
cout<<"-1";
return 0;
}
vc[b].push_back({a,-1});
}
if(x==5)vc[a].push_back({b,0});
}
spfa();
return 0;
}
补:
双端队列优化,用别人博客的优化不行,用deepseek的就行,也不知道这是什么原理,出题人故意卡spfa真恶心
#include<iostream>
#include<queue>
#include<deque>
#include<vector>
#define int long long
using namespace std;
char* p1, * p2, buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x = 0, f = 1;
char ch = nc();
while (ch < 48 || ch>57)
{
if (ch == '-')
f = -1;
ch = nc();
}
while (ch >= 48 && ch <= 57)
x = x * 10 + ch - 48, ch = nc();
return x * f;
}
const int N=1e6+10;
struct node{
int id,dis;
};
int cnt[N];
int vis[N];
vector<node>vc[N];
int w[N];
int n,k;
void spfa(){
deque<int>q;
for(int i=1;i<=n;i++){
vc[0].push_back({i,1});
}
for(int i=0;i<=n;i++)w[i]=-1e9;
w[0]=0;
for(int i=0;i<=n;i++)q.push_back(i),vis[i]=1;
while(!q.empty()){
int u=q.front();
q.pop_front();
vis[u]=0;
for(int i=0;i<vc[u].size();i++){
int v=vc[u][i].id;
if(w[u]+vc[u][i].dis>w[v]){
w[v]=w[u]+vc[u][i].dis;
cnt[v]=cnt[u]+1;
if(cnt[v]>=n+1){
cout<<"-1";
return;
}
if(!vis[v]){
if(!q.empty()&&w[v]>w[q.front()]){
q.push_front(v);
}
else q.push_back(v);
vis[v]=1;
}
}
}
}
int sum=0;
for(int i=1;i<=n;i++)sum+=w[i];
cout<<sum;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
while(k--){
int x,a,b;
cin>>x>>a>>b;
if(x==1)vc[a].push_back({b,0}),vc[b].push_back({a,0});
if(x==2){
if(a==b){
cout<<"-1";
return 0;
}
vc[a].push_back({b,1});
}
if(x==3)vc[b].push_back({a,0});
if(x==4){
if(a==b){
cout<<"-1";
return 0;
}
vc[b].push_back({a,1});
}
if(x==5)vc[a].push_back({b,0});
}
spfa();
return 0;
}
分类:
图 / 最短路
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理