最大流最小割入门题
Dinic板子:
const int tmax=1e4+5,inf_int=1e9+5; struct edge{ int to,cap,rev; }; vector<edge> G[tmax]; int level[tmax]; int iter[tmax]; void addedge(int from,int to,int cap) { G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1}); } void bfs(int s) { memset(level,-1,sizeof(level)); queue<int> que; level[s]=0; que.push(s); while(!que.empty()) { int v=que.front(); que.pop(); for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f) { if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&level[v]<level[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int Dinic(int s,int t) { int flow=0; while(1) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf_int))>0) flow+=f; } }
Dijkstra+Heap板子:
const int tmax=1e4+5,inf_int=1e9+5; ll dis1[tmax], dis2[tmax]; struct node { ll d; int x; bool operator<(const node &b)const { return d>b.d; } }; vector<Pii> GG[tmax]; priority_queue<node> Q; bool vis[tmax]; void dijk(int s,ll *d) { int i,u,v,w,len; node tmp; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) d[i]=inf; d[s]=0; Q.push((node){0,s}); while(!Q.empty()) { tmp=Q.top(); Q.pop(); u=tmp.x; if(vis[u]) continue; vis[u]=true; len=GG[u].size(); for(i=0;i<len;i++) { v=GG[u][i].first; w=GG[u][i].second; if(d[v]>d[u]+w) { d[v]=d[u]+w; Q.push((node){d[v],v}); } } } return; }
HDU 3416
题意:给出一个图,有多少个边不重复的最短路。
题解:先跑最短路,找出从start到end的所有最短路,先跑正向在跑反向,如果dis1[u]+cost[i]+dist2[v]==dis1[n],即可判断该边是否在最短路上。
把最短上的边构图(cap=1)跑最大流即可.
#include <bits/stdc++.h> #define Pii pair<int,int> using namespace std; typedef long long ll; const ll inf=1e16; const int tmax=2e5+5,inf_int=1e9+5; int n, m, u[tmax], v[tmax], c[tmax]; ll dis1[tmax], dis2[tmax]; struct node { ll d; int x; bool operator<(const node &b)const { return d>b.d; } }; vector<Pii> GG[tmax]; priority_queue<node> Q; bool vis[tmax]; void Dijk(int s,ll *d) { int i,u,v,w,len; node tmp; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) d[i]=inf; d[s]=0; Q.push((node){0,s}); while(!Q.empty()) { tmp=Q.top(); Q.pop(); u=tmp.x; if(vis[u]) continue; vis[u]=true; len=GG[u].size(); for(i=0;i<len;i++) { v=GG[u][i].first; w=GG[u][i].second; if(d[v]>d[u]+w) { d[v]=d[u]+w; Q.push((node){d[v],v}); } } } return; } struct edge{ int to,cap,rev; }; vector<edge> G[tmax]; int level[tmax]; int iter[tmax]; void addedge(int from,int to,int cap) { G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1}); } void bfs(int s) { memset(level,-1,sizeof(level)); queue<int> que; level[s]=0; que.push(s); while(!que.empty()) { int v=que.front(); que.pop(); for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f) { if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&level[v]<level[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int Dinic(int s,int t) { int flow=0; while(1) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf_int))>0) flow+=f; } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T; for(cin>>T; T--; ) { cin>>n>>m; for(int i=1; i<=m; i++) { cin>>u[i]>>v[i]>>c[i]; GG[u[i]].push_back(Pii(v[i],c[i])); } int A, B; cin>>A>>B; Dijk(A, dis1); for(int i=1; i<=n; i++) GG[i].clear(); for(int i=1; i<=m; i++) GG[v[i]].push_back(Pii(u[i],c[i])); Dijk(B, dis2); for(int i=1; i<=m; i++) { if(dis1[u[i]]+c[i]+dis2[v[i]]==dis1[B]) addedge(u[i],v[i],1); } cout<<Dinic(A,B)<<endl; for(int i=1; i<=n; i++) { G[i].clear(); GG[i].clear(); } } return 0; }
HDU 6532
题意:给出一个图,求至少删除多少边权后能够最短路长度增加(删除后不联通可以)
题解:以最短路上的边构图,跑一下最小割即可。
#include <bits/stdc++.h> #define Pii pair<int,int> using namespace std; typedef long long ll; const ll inf=1e16; const int tmax=1e4+5,inf_int=1e9+5; int n, m, u[tmax], v[tmax], c[tmax]; ll dis1[tmax], dis2[tmax]; struct node { ll d; int x; bool operator<(const node &b)const { return d>b.d; } }; vector<Pii> GG[tmax]; priority_queue<node> Q; bool vis[tmax]; void Dijk(int s,ll *d) { int i,u,v,w,len; node tmp; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) d[i]=inf; d[s]=0; Q.push((node){0,s}); while(!Q.empty()) { tmp=Q.top(); Q.pop(); u=tmp.x; if(vis[u]) continue; vis[u]=true; len=GG[u].size(); for(i=0;i<len;i++) { v=GG[u][i].first; w=GG[u][i].second; if(d[v]>d[u]+w) { d[v]=d[u]+w; Q.push((node){d[v],v}); } } } return; } struct edge{ int to,cap,rev; }; vector<edge> G[tmax]; int level[tmax]; int iter[tmax]; void addedge(int from,int to,int cap) { G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1}); } void bfs(int s) { memset(level,-1,sizeof(level)); queue<int> que; level[s]=0; que.push(s); while(!que.empty()) { int v=que.front(); que.pop(); for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f) { if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&level[v]<level[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int Dinic(int s,int t) { int flow=0; while(1) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf_int))>0) flow+=f; } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T; for(cin>>T; T--; ) { cin>>n>>m; for(int i=1; i<=m; i++) { cin>>u[i]>>v[i]>>c[i]; GG[u[i]].push_back(Pii(v[i], c[i])); } Dijk(1, dis1); for(int i=1; i<=n; i++) GG[i].clear(); for(int i=1; i<=m; i++) GG[v[i]].push_back(Pii(u[i],c[i])); Dijk(n,dis2); for(int i=1; i<=m; i++) { if(dis1[u[i]]+c[i]+dis2[v[i]]==dis1[n]) addedge(u[i],v[i],c[i]); } cout<<Dinic(1,n)<<endl; for(int i=1; i<=n; i++) { G[i].clear(); GG[i].clear(); } } return 0; }