差分约束_训练总结
关于建边,如果需要求最小值(即最长路),一开始的话add(v,u,-w);
另外如果xi-xj<=k,那么建边(j,i,k)这个样子
推荐博客:https://blog.csdn.net/consciousman/article/details/53812818
洛谷P5960:https://www.luogu.com.cn/problem/P5960
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int tot,head[maxn]; struct E{ int to,next,w; }edge[maxn<<1]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } int n,m; int d[maxn],inq[maxn],cnt[maxn]; bool SPFA(int s){ queue<int> q; q.push(s);d[s]=0,inq[s]=1; while(!q.empty()){ int now=q.front();q.pop(); inq[now]=0; for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to; if(d[v]>d[now]+edge[i].w){ d[v]=d[now]+edge[i].w; cnt[v]=cnt[now]+1; if(cnt[v]>=n) return true; if(inq[v]==1) continue; q.push(v); } } } return false; } int main(){ cin>>n>>m;mem(head,-1); rep(i,1,m){ int u,v,w;cin>>u>>v>>w; add(v,u,w); } rep(i,1,n) add(0,i,0); mem(d,INF); if(SPFA(0)) puts("NO"); else{ rep(i,1,n){ cout<<d[i]<<" "; } puts(""); } }
求最小值(SPFA最长路),洛谷P1250种树
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int tot,head[maxn]; struct E{ int to,next,w; }edge[maxn<<1]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } int n,m; int d[maxn],inq[maxn],cnt[maxn]; queue<int> q; bool SPFA(int s){ q.push(s);d[s]=0,inq[s]=1; while(!q.empty()){ int now=q.front();q.pop(); inq[now]=0; for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to; if(d[v]<d[now]+edge[i].w){ d[v]=d[now]+edge[i].w; cnt[v]++; if(cnt[v]>=n) return true; if(!inq[v]){ inq[v]=1; q.push(v); } } } } return false; } int main(){ cin>>n>>m;mem(head,-1); rep(i,1,m){ int u,v,w;cin>>u>>v>>w; add(u-1,v,w); } mem(d,-INF); rep(i,1,n){ add(i-1,i,0); if(i!=0) add(i,i-1,-1); } rep(i,0,n) add(n+1,i,0); SPFA(n+1); cout<<d[n]<<endl; }
洛谷P2294,这个题限定条件 w<=Xv-X(u-1)<=W,所以建边要注意了
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int tot,head[maxn]; struct E{ int to,next,w; }edge[maxn<<1]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } int n,m; int d[maxn],inq[maxn],cnt[maxn]; queue<int> q; bool SPFA(int s){ q.push(s);d[s]=0,inq[s]=1; while(!q.empty()){ int now=q.front();q.pop(); inq[now]=0; for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to; if(d[v]>d[now]+edge[i].w){ d[v]=d[now]+edge[i].w; cnt[v]=cnt[now]+1; if(cnt[v]>=n) return true; if(inq[v]==1) continue; q.push(v); } } } return false; } int main(){ int T;cin>>T; while(T--){ mem(d,INF);mem(cnt,0);mem(inq,0);mem(head,-1),tot=0; while(!q.empty()) q.pop(); cin>>n>>m; rep(i,1,m){ int u,v,w;cin>>u>>v>>w; add(v,u-1,-w); add(u-1,v,w); } rep(i,0,n){ add(n+1,i,0); } if(SPFA(n+1))puts("false"); else puts("true"); } }
洛谷P3275
这里因为是求最小数,需要建立最长路跑SPFA,建图过程和之前的那些不太一样,SPFA算法里的cnt统计以及的松弛过程都不一样。
这道题坑很多,倒叙从n~1建可以玄学不被卡常
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=2e5+5; int tot,head[maxn]; struct E{ int to,next,w; }edge[maxn<<1]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } int n,m; int d[maxn],inq[maxn],cnt[maxn]; queue<int> q; bool SPFA(int s){ q.push(s);d[s]=0,inq[s]=1; while(!q.empty()){ int now=q.front();q.pop(); inq[now]=0; for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to; if(d[v]<d[now]+edge[i].w){ d[v]=d[now]+edge[i].w; cnt[v]++; if(cnt[v]>=n) return true; if(!inq[v]){ inq[v]=1; q.push(v); } } } } return false; } int main(){ scanf("%d%d",&n,&m);mem(head,-1); rep(i,1,m){ int op,a,b;scanf("%d%d%d",&op,&a,&b); if(op%2==0&&a==b){puts("-1");return 0;} if(op==1){add(b,a,0);add(a,b,0);} if(op==2){add(a,b,1);} if(op==3){add(b,a,0);} if(op==4){add(b,a,1);} if(op==5){add(a,b,0);} } per(i,n,1) add(0,i,1); if(SPFA(0)){puts("-1");} else{ ll ans=0; rep(i,1,n){ ans+=d[i]; } cout<<ans<<endl; } }
前ICPC算法竞赛退役选手|现摸鱼ing