学网络流也有两个月了吧,要发一下代码了吧。
说实话反向边那些东西十分简单,理解了就好
费用流也就是一个SPFA加一句话,水爆了
最烦连边了,连完了打板子,啥都不想
例题:
POJ1273 草地排水
板子题,看板子过
奇丑无比的FF加上强迫症的代码风格:
#include<cstdio>
#include<algorithm>
#include<cstring>
#define inf 99999999
using namespace std;
const int maxn=205,maxm=maxn<<1;
int fir[maxn],nxt[maxm],w[maxm],dis[maxm];
int n,m;
inline int gi();
inline void adde(int a,int b,int W,int id){nxt[id]=fir[a],fir[a]=id,dis[id]=b,w[id]=W;}
inline int rev(int id){if(id&1)return id+1;else return id-1;}
void init();void work();int dfs(int,int,int);
int main(){while(scanf("%d%d",&m,&n)==2)init(),work();return 0;}
void init(){
memset(fir,0,sizeof(fir));
int a,b,c;
for(int i=1;i<=m;i++)
a=gi(),b=gi(),c=gi(),adde(a,b,c,(i<<1)-1),adde(b,a,0,i<<1);
}
bool vis[maxn];
void work(){
int ans=0,D=1;
while(D){
memset(vis,0,sizeof(vis));
D=dfs(1,n,inf),ans+=D;
}
printf("%d\n",ans);
}
int dfs(int now,int end,int minn){
if(now==end)return minn;
vis[now]=1;
for(int i=fir[now];i;i=nxt[i]){
if(!vis[dis[i]]&&w[i]>0){
register int down=dfs(dis[i],end,min(minn,w[i]));
if(down){
w[i]-=down,w[rev(i)]+=down;
return down;
}
}
}
return 0;
}
int gi() {
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
【网络流24题】最长递增子序列
板子题,DP之后连边比较奇特(实力还弱啊QAQ)
奇丑无比的inf都不define的无聊代码(最讨厌这种几问的题):
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define t (dis[i])
using namespace std;
inline int gi() {
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')f=(ch=='-')?-1:f,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*f;
}
inline void Dp();
inline void solve(int);
int X[501],F[501];
int n,K,S,T;
int main() {
n=gi();
for(int i=1; i<=n; i++)X[i]=gi();
Dp();
S=n+1,T=n+2,solve(1),solve(1000);
return 0;
}
const int maxn=521,maxm=400001<<1;
int fir[maxn],dis[maxm],w[maxm],nxt[maxm],dep[maxn];
inline void Dp() {
int ans=0;
for(int i=1; i<=n; i++) {
F[i]=1;
for(int j=1; j<i; j++)if(X[j]<=X[i])F[i]=max(F[i],F[j]+1);
ans=max(F[i],ans);
}
printf("%d\n",K=ans);
}
int Index=1;
inline void adde(int a,int b,int ww) {
nxt[++Index]=fir[a],fir[a]=Index,dis[Index]=b,w[Index]=ww;
if(ww)adde(b,a,0);
}
inline bool BFS() {
queue<int>bfs;
memset(dep,0,sizeof dep);
bfs.push(S);
bool yes[600]= {0};
yes[S]=1,dep[S]=0;
while(!bfs.empty()) {
int now=bfs.front();
for(int i=fir[now]; i; i=nxt[i])
if(w[i]>0&&!yes[t])
yes[t]=1,bfs.push(t),dep[t]=dep[now]+1;
bfs.pop();
}
return yes[T];
}
inline int Dinic(int now,int h) {
if(now==T)return h;
int ans=0;
for(int i=fir[now]; i; i=nxt[i])
if(w[i]>0&&dep[t]==dep[now]+1) {
int D=Dinic(t,min(h,w[i]));
w[i]-=D,w[i^1]+=D,ans+=D,h-=D;
if(h==0)return ans;
}
return ans;
}
inline void solve(int hehe) {
memset(fir,0,sizeof fir);
Index=1;
for(int i=1; i<n; i++)
for(int j=i+1; j<=n; j++)
if(X[i]<=X[j]&&F[i]+1==F[j])adde(i,j,1);
if(hehe^1) {
adde(S,1,hehe);
for(int i=2; i<=n; i++)if(F[i]==1)adde(S,i,1);
for(int i=1; i<n; i++)if(F[i]==K)adde(i,T,1);
if(F[n]==K)adde(n,T,hehe);
} else {
for(int i=1; i<=n; i++)if(F[i]==1)adde(S,i,1);
for(int i=1; i<=n; i++)if(F[i]==K)adde(i,T,1);
}
int ans=0;
while(BFS())ans+=Dinic(S,10000000);
printf("%d\n",ans);
}
【网络流24题】数字梯形(费用流):#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define inf 10000000
#define up +0
#define down +1
#define t (dis[i])
const int maxn=1001<<1,maxm=10000<<1,S=2000,T=2001;
using namespace std;
int fir[maxn],dis[maxm],w[maxm],cost[maxm],nxt[maxm],id=1,m,n;
int INDEX=0;
inline void add(int a,int b,int c,int d,int e=0){
nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d;
if(c)add(b,a,0,e);
}
int num[21][41],Index[21][41];
inline void build(int a,int b){
memset(fir,0,sizeof fir);
for(int i=1;i<=m;i++)add(S,Index[1][i]up,1,0);
for(int i=1;i<=m+n-1;i++)add(Index[n][i]down,T,a,0);
for(int i=1;i<n;i++)
for(int j=1;j<m+i;j++){
add(Index[i][j]up,Index[i][j]down,a,-num[i][j],num[i][j]);
add(Index[i][j]down,Index[i+1][j]up,b,0);
add(Index[i][j]down,Index[i+1][j+1]up,b,0);
}
for(int j=1;j<m+n;j++)
add(Index[n][j]up,Index[n][j]down,a,-num[n][j],num[n][j]);
}
int que[maxn],vis[maxn],pre[maxn],Dis[maxn];
inline bool spfa(){
int hd=1,tl=1;
for(int i=1;i<=INDEX;i++)Dis[i]=inf;
memset(vis,0,sizeof vis);
Dis[T]=inf,Dis[S]=0,que[tl++]=S,vis[S]=1;
while(hd^tl){
int now=que[hd];
for(int i=fir[now];i;i=nxt[i])
if(w[i]>0&&Dis[t]>Dis[now]+cost[i]){
Dis[t]=Dis[now]+cost[i],pre[t]=i;
if(!vis[t])vis[t]=1,que[tl]=t,tl=(tl+1)%maxn;
}
vis[now]=0,hd=(hd+1)%maxn;
}
return Dis[T]!=inf;
}
inline int end(int&flow,int sum=inf,int ret=0){
for(int now=T,p;now^S;now=dis[p^1])p=pre[now],sum=min(sum,w[p]);
for(int now=T,p;now^S;now=dis[p^1])p=pre[now],w[p]-=sum,w[p^1]+=sum,ret+=cost[p];
flow+=sum;return ret*sum;
}
inline int maxflow(int ans=0,int flow=0){
while(spfa())ans+=end(flow);
return -ans;
}
int main(){
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++)
for(int j=1;j<=m+i;j++)
scanf("%d",&num[i+1][j]),Index[i+1][j]=++INDEX,++INDEX;
build(1,1),printf("%d\n",maxflow());
build(inf,1),printf("%d\n",maxflow());
build(inf,inf),printf("%d\n",maxflow());
return 0;
}
【网络流24题】运输问题(费用流):
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define rg register
#define t (dis[i])
using namespace std;
const int maxd=230,S=maxd-2,T=maxd-1,maxm=maxd*maxd<<1,inf=1000000000;
int m,n,a[101],b[101];
inline int gi() {
rg int x=0;
rg char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
int fir[maxd],nxt[maxm],dis[maxm],cost[maxm],w[maxm],id=1;
inline void add(int a,int b,int c,int d){
nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d;
if(c)add(b,a,0,-d);
}
inline bool spfa(int&FLOW,int&COST){
int hd=1,tl=1,que[maxd],inque[maxd]={0},pre[maxd],Dis[maxd];
que[tl++]=S,inque[S]=1;
for(int i=1;i<=m+n;i++)Dis[i]=inf;Dis[T]=inf,Dis[S]=0;
while(hd^tl){
int now=que[hd];
for(int i=fir[now];i;i=nxt[i])
if(w[i]>0&&Dis[t]>Dis[now]+cost[i]){
Dis[t]=Dis[now]+cost[i],pre[t]=i;
if(!inque[t])inque[t]=1,que[tl++]=t,tl%=maxd;
}
hd=(hd+1)%maxd,inque[now]=0;
}
if(Dis[T]==inf)return 0;
int flow=inf;
for(int now=T,p;now^S;now=dis[p^1])p=pre[now],flow=min(flow,w[p]);
for(int now=T,p;now^S;now=dis[p^1])p=pre[now],w[p]-=flow,w[p^1]+=flow,COST+=flow*cost[p];
FLOW+=flow; return 1;
}
inline int mincost(int Flow=0,int Cost=0){
while(spfa(Flow,Cost));return Cost;
}
int main(){
m=gi(),n=gi();
for(rg int i=1;i<=m;i++)a[i]=i,add(S,a[i],gi(),0);
for(rg int i=1;i<=n;i++)b[i]=i+m,add(b[i],T,gi(),0);
for(rg int i=1;i<=m;i++)for(int j=1;j<=n;j++)add(a[i],b[j],inf,gi());
printf("%d\n",mincost());
for(rg int i=2;i<=id;i+=2)w[i]+=w[i^1],w[i^1]=0,cost[i]=-cost[i],cost[i^1]=-cost[i^1];
printf("%d\n",-mincost());
return 0;
}
【中学高级本-网络流24题】餐巾计划(较难,看了题解,但还是费用流):
#include<cstdio>
#include<algorithm>
#define X(o) ((o)<<1)
#define Y(o) ((o)<<1|1)
#define t (dis[i])
#define rg register
using namespace std;
int n,r[222],P,fast,slow,fastc,slowc;
const int maxd=420,maxm=23333,S=410,T=411,inf=233333333;
inline int gi() {
rg int x=0;
rg char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
int fir[maxd],nxt[maxm],dis[maxm],w[maxm],cost[maxm],id=1;
inline void add(int a,int b,int c,int d){
nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d;
if(c)add(b,a,0,-d);
}
inline void build(){
for(rg int i=1;i<=n;i++){
add(S,X(i),r[i],0),add(S,Y(i),inf,P);
add(Y(i),T,r[i],0);
add(X(i),X(i+1),inf,0);
if(i+fast<=n)add(X(i),Y(i+fast),inf,fastc);
if(i+slow<=n)add(X(i),Y(i+slow),inf,slowc);
}
}
inline bool spfa(int&F,int&C){
int que[maxd],pre[maxd],Dis[maxd];bool inque[maxd]={0};
rg int hd=1,tl=1;
que[tl++]=S,inque[S]=1;
for(rg int i=1;i<=Y(n);i++)Dis[i]=inf;Dis[T]=inf,Dis[S]=0;
while(hd^tl){
rg int now=que[hd];
for(rg int i=fir[now];i;i=nxt[i])
if(w[i]>0&&Dis[t]>Dis[now]+cost[i]){
Dis[t]=Dis[now]+cost[i],pre[t]=i;
if(!inque[t])que[tl++]=t,tl%=maxd,inque[t]=1;
}
hd=(hd+1)%maxd,inque[now]=0;
}
if(Dis[T]==inf)return 0;
rg int sum=inf;
for(int now=T,p;now^S;now=dis[p^1])p=pre[now],sum=min(sum,w[p]);
for(int now=T,p;now^S;now=dis[p^1])p=pre[now],w[p]-=sum,w[p^1]+=sum,C+=cost[p]*sum;
F+=sum;
return 1;
}
inline int mincost(int Flow=0,int Cost=0){
while(spfa(Flow,Cost));return Cost;
}
int main(){
n=gi();
for(rg int i=1;i<=n;i++)r[i]=gi();
P=gi(),fast=gi(),fastc=gi(),slow=gi(),slowc=gi();
build();
printf("%d\n",mincost());
return 0;
}
只学了最大流和费用流,比较蒟蒻,什么什么割的什么流还没学(貌似叫最小割最大流吧)