有關網路流的一些板子題
阿新 • • 發佈:2020-08-20
最大流 (洛谷 3376)
#include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> #include<iostream> #include<cstring> #include<cmath> using namespace std; #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i) #define per(i,n,a) for (int i=n;i>=a;i--) #define MT(x,i) memset(x,i,sizeof(x) ) #define rev(i,start,end) for (int i=start;i<end;i++) #define inf 0x3f3f3f3f #define mp(x,y) make_pair(x,y) #define lowbit(x) (x&-x) #define MOD 1000000007 #define exp 1e-8 #define N 1000005 #define fi first #define se second #define pb push_back typedef long long ll; typedef pair<int ,int> PII; ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; } const int maxn=520010; const ll INF=2005020600; int head[maxn]; int n,m,s,t,u,v; int now[maxn],cnt=1; ll dis[maxn],ans,w; struct edge { int v,next; ll val; // edge (int v=0,int next=0,ll val=0): v(v), next(next), val(val) {} }e[maxn]; inline void add (int u,int v,ll w) { e[++cnt].v=v; e[cnt].val=w; //加正反兩條邊 e[cnt].next=head[u]; head[u]=cnt; e[++cnt].v=u; e[cnt].val=0; e[cnt].next=head[v]; head[v]=cnt; } inline int bfs () { //求分層圖 rep (i,1,n) dis[i]=INF; queue <int > q; dis[s]=0; now[s]=head[s]; q.push (s); while (q.size ()) { int x=q.front (); q.pop(); for (int i=head[x];i;i=e[i].next) { int v=e[i].v; if (e[i].val>0&&dis[v]==INF) { //直接遍歷鄰邊判斷即可 q.push (v); now[v]=head[v]; dis[v]=dis[x]+1; if (v==t) return 1; } } } return 0; } inline ll dfs (int x,ll sum) { if (x==t) return sum; ll k,res=0; for (int i=now[x];i&∑i=e[i].next) { now[x]=i; int v=e[i].v; if (e[i].val>0&&(dis[v]==dis[x]+1)) { k=dfs (v,min (sum,e[i].val)); //剩餘流量最小值 if (k==0) dis[v]=INF; e[i].val-=k; //更新殘量網路 e[i^1].val+=k; res+=k; //更新當前答案和剩餘流量 sum-=k; } } return res; } int main () { // freopen ("data.in","r",stdin); scanf ("%d%d%d%d",&n,&m,&s,&t); rep (i,1,m) { scanf ("%d%d%lld",&u,&v,&w); add (u,v,w); } while (bfs ()) { //如果還存在合法分層圖,累加答案 ans+=dfs (s,INF); } printf ("%lld",ans); // fclose (stdin); return 0; }
最小費用最大流
#include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i) #define per(i,n,a) for (int i=n;i>=a;i--) #define MT(x,i) memset(x,i,sizeof(x) ) #define rev(i,start,end) for (int i=start;i<end;i++) #define inf 0x3f3f3f3f #define mp(x,y) make_pair(x,y) #define lowbit(x) (x&-x) #define MOD 1000000007 #define exp 1e-8 #define N 1000005 #define fi first #define se second #define pb push_back typedef long long ll; typedef vector <int> VI; typedef pair<int ,int> PII; typedef pair<int ,PII> PIII; ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; } inline int read() { char ch=getchar(); int x=0, f=1; while(ch<'0'||ch>'9') { if(ch=='-') f = -1; ch=getchar(); } while('0'<=ch&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } const int maxn=5e4+10; const int M=5e3+10; int n,m,s,t,cnt=1; int head[maxn],dis[maxn],pre[maxn],incf[maxn]; int maxflow,mincost; bool vis[maxn]; struct edge { int v,next,flow,cost; }e[M<<1]; inline void add (int u,int v,int flow,int cost) { e[++cnt]= (edge) {v,head[u],flow,cost}; head[u]=cnt; } inline void add_edge (int u,int v,int flow,int cost) { add (u,v,flow,cost); add (v,u,0,-cost); } inline bool spfa () { queue <int > q; MT (dis,0x3f); MT (vis,0); q.push (s); dis[s]=0; vis[s]=1; incf[s]=1<<30; while (q.size ()) { int x=q.front (); q.pop (); vis[x]=0; for (int i=head[x];i;i=e[i].next) { if (!e[i].flow) continue; int v=e[i].v; if (dis[v]>dis[x]+e[i].cost) { dis[v]=dis[x]+e[i].cost; incf[v]=min (incf[x],e[i].flow); pre[v]=i; if (!vis[v]) vis[v]=1,q.push (v); } } } if (dis[t]==inf) return 0; return dis[t]; } inline void mcmf () { while (spfa ()) { int x=t; maxflow+=incf[t]; mincost+=dis[t]*incf[t]; int i; while (x!=s) { i=pre[x]; e[i].flow-=incf[t]; e[i^1].flow+=incf[t]; x=e[i^1].v; } } } int main () { scanf ("%d%d%d%d",&n,&m,&s,&t); rep (i,1,m) { int u,v,w,c; scanf ("%d%d%d%d",&u,&v,&w,&c); add_edge (u,v,w,c); } mcmf (); printf ("%d %d\n",maxflow,mincost); return 0; }