分析
差分约束:
答案求最小值,不等式变形为“>=",跑最长路
答案求最大值,不等式变形为"<=",跑最短路
对于这道题,根据操作选择点连边
最后,不要忘了隐含条件:每个人至少分一个糖果,所以就是
d
[
i
]
>
=
1
d[i]>=1
d[i]>=1
d
[
i
]
−
0
>
=
1
d[i]-0>=1
d[i]−0>=1
从0往 i 建一条边,权值为1
此题有坑,需注意:
1.特判,操作2,3给出的两个人相同
2.从0往外连边时,需要倒序连(不知道为什么,网上说是数据有一条链,但还是不明白啊,怎么会被卡了?)
今日份小总结
写代码就像写作文
要先设计出来(画一下流程)然后就可以知道哪些要封装
不是说边写边想,一定要想好了再写
调试永远比写代码耗时久
所以一定要在写的时候就思考好,规划好
Code
#include<bits/stdc++.h>
#define in read()
#define M 500009
#define N 200009
#define ll long long
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
int n,m;
int d[N];
int nxt[M],to[M],head[N],w[M],ecnt=0;
void add(int x,int y,int z){
nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;w[ecnt]=z;
}
int ok=0,cnt[N];
bool vis[N];
void spfa(int S){
queue<int> q;q.push(S);d[S]=0;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
if(d[v]>d[u]+w[e]){
d[v]=d[u]+w[e];
if(!vis[v]) {
vis[v]=1;
cnt[v]++;
if(cnt[v]>n) {ok=1;return;}//bfs的判断
q.push(v);
}
}
}
}
}
int main(){
memset(d,127,sizeof(d));
n=in;m=in;
int i,j,k;
int a,b;
for(i=n;i>=1;--i) add(0,i,-1);/一定要逆序
for(i=1;i<=m;++i){
int op=in;a=in;b=in;
if(op==1){ add(b,a,0);add(a,b,0); }/tepan
if(op==2){ add(a,b,-1);if(a==b) return printf("-1"),0; }
if(op==3){ add(b,a,0); }
if(op==4){ add(b,a,-1);if(a==b) return printf("-1"),0; }
if(op==5){ add(a,b,0); }
}
d[0]=0;
spfa(0);
if(ok) return printf("-1"),0;
ll ans=0;
for(i=1;i<=n;++i){
ans+=1ll*d[i];
}
printf("%lld\n",-ans);
return 0;
}cpp