差分約束_訓練總結
阿新 • • 發佈:2020-07-16
關於建邊,如果需要求最小值(即最長路),一開始的話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--) #defineView Codeendl '\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]; 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-1,-w); } rep(i,1,n){ add(i-1,i,1); add(i,i-1,0); } rep(i,0,n) add(n+1,i,0); mem(d,INF); SPFA(n+1); int minn=INF; rep(i,0,n){ minn=min(minn,d[i]); } cout<<d[n]<<endl; cout<<d[n]-minn<<endl; }View Code
洛谷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"); } }View Code
洛谷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; } }View Code