放上一下模板的好。毕竟老忘。
Dinic: while(BFS()) ans+=DFS(S, ∞)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#if 0
Writers: Goes && G.S.M.
Have falled in love
#endif
inline int read(){
char ch=getchar();int sum=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
sum*=10,sum+=ch-'0',ch=getchar();
return sum;
}
const int N=1000010;
const int INF=(1<<30);
struct ss{
int to,nex,va;
}edge[N<<1];
int head[N],ecnt=1;
int n,m,s,t;
void add(int va,int y,int x){
edge[++ecnt]=(ss){y,head[x],va};
edge[++ecnt]=(ss){x,head[y],0};
head[x]=ecnt-1;head[y]=ecnt;
}
int level[N];
bool BFS(){
memset(level,0,sizeof(level));
level[s]=1;queue<int>Q;Q.push(s);
while(!Q.empty()){
int pos=Q.front();Q.pop();
for(int i=head[pos];i;i=edge[i].nex)
if(edge[i].va&&!level[edge[i].to]){
level[edge[i].to]=level[pos]+1;
Q.push(edge[i].to);
}
}return level[t];
}
int DFS(int pos,int mflow){
if(!mflow||pos==t)return mflow;int ret=0;
for(int i=head[pos];i;i=edge[i].nex)
if(edge[i].va&&level[edge[i].to]==level[pos]+1)
{
int temp=DFS(edge[i].to,min(mflow,edge[i].va));
ret+=temp;mflow-=temp;edge[i].va-=temp;
edge[i^1].va-=temp;
}return ret;
}
inline int Dinic(){
int ret=0;while(BFS())ret+=DFS(s,INF);
return ret;
}
int main(){
n=read(),m=read(),s=read(),t=read();
for(int i=1;i<=m;i++)
add(read(),read(),read());
printf("%d",Dinic());return 0;
}
ISAP:一次BFS定级,后续按最近点级数修改。
优化关键:gap优化,cur数组的优化
思路:能往下流就往下流,不能流了回溯修改。
(60ms……比dinic的300ms 靠谱多了……emmmm…..)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#if 0
Writers: Goes && G.S.M.
Have falled in love
#endif
const int N=100007;
const int INF=(1<<30);
inline int read(){
char ch=getchar();int sum=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
sum*=10,sum+=ch-'0',ch=getchar();
return sum;
}
int n,m,S,T;
struct ss{
int to,nex,va;
}edge[N<<1];int head[N],ecnt=1;
void add(int va,int y,int x){
edge[++ecnt]=(ss){y,head[x],va};
edge[++ecnt]=(ss){x,head[y],0};
head[x]=ecnt-1;head[y]=ecnt;
}
int dis[N],num[N],cur[N],fa[N];
void BFS(){
for(int i=1;i<=n;i++) dis[i]=N;
queue<int>Q;Q.push(T);dis[T]=0;
while(!Q.empty()){
int pos=Q.front();Q.pop();
for(int i=head[pos];i;i=edge[i].nex)
if(edge[i^1].va&&dis[edge[i].to]>dis[pos]+1)
{
dis[edge[i].to]=dis[pos]+1;
Q.push(edge[i].to);
}
}return ;
}
int out(){
int pos=T,f=INF;
while(pos!=S)pos=fa[pos],f=min(f,edge[cur[pos]].va);
pos=T;
while(pos!=S)pos=fa[pos],
edge[cur[pos]].va-=f,
edge[cur[pos]^1].va+=f;
return f;
}
inline int gswork(){
BFS();int pos=S,flow=0;
for(int i=1;i<=n;i++)
num[dis[i]]++,cur[i]=head[i];
while(dis[S]<n){
if(pos==T)flow+=out(),pos=S;
bool done = false;
for(int i=cur[pos];i;i=edge[i].nex)
if(edge[i].va&&dis[pos]==dis[edge[i].to]+1)
{
fa[edge[i].to]=pos;cur[pos]=i;
pos=edge[i].to;done=true;i=0;
}
if(!done){
int minx=n;
for(int i=head[pos];i;i=edge[i].nex)
if(edge[i].va) minx=min(minx,dis[edge[i].to]);
if(--num[dis[pos]]==0)break;
num[dis[pos]=minx+1]++;cur[pos]=head[pos];
if(pos!=S)pos=fa[pos];
}
}return flow;
}
inline void gsin(){
n=read();m=read();S=read(),T=read();
for(int i=1;i<=m;i++)
add(read(),read(),read());
}
int main(){gsin();printf("%d",gswork());return 0;}
费用流(dinic)
[一个道理吧……]
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
inline int read(){
char ch=getchar();int sum=0,f=1;
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')
sum*=10,sum+=ch-'0',ch=getchar();
return sum*f;
}
#if 0
Writers: G.S.M. && Goes
#endif
const int M=100100;
const int N=10010;
const int INF=0x3f3f3f3f;
struct ss{
int to,nex,va,cap;
}edge[M];int head[N],ecnt=1;
void add(int va,int cap,int y,int x){
edge[++ecnt]=(ss){y,head[x],va,cap};
edge[++ecnt]=(ss){x,head[y],-va,0};
head[x]=ecnt-1;head[y]=ecnt;
}
int n,m,S,T;int res,ans;
int dis[N],inq[N],vis[N];
bool bfs(){
for(int i=0;i<=n;i++)dis[i]=INF;
memset(inq,0,sizeof(inq));
queue<int>Q;Q.push(T);inq[T]=true;dis[T]=0;
while(!Q.empty()){
int pos=Q.front();Q.pop();inq[pos]=false;
for(int i=head[pos];i;i=edge[i].nex)
if(edge[i^1].cap&&dis[edge[i].to]>dis[pos]-edge[i].va){
dis[edge[i].to]=dis[pos]-edge[i].va;
if(!inq[edge[i].to]){
inq[edge[i].to]=true;
Q.push(edge[i].to);
}
}
}return dis[S]<INF;
}
int dfs(int pos,int flow){
vis[pos]=true;int res=0;
if(pos==T||!flow)return flow;
for(int i=head[pos];i;i=edge[i].nex)
if((!vis[edge[i].to])&&edge[i].cap&&
dis[edge[i].to]==dis[pos]-edge[i].va){
int w=flow-res;
w=dfs(edge[i].to,min(edge[i].cap,w));
edge[i].cap-=w;edge[i^1].cap+=w;
res+=w;if(res==flow)return res;
}return res;
}
int main()
{
n=read(),m=read(),S=read(),T=read();
for(int i=1;i<=m;i++)
add(read(),read(),read(),read());
while(bfs()){
vis[T]=true;
while(vis[T]){
memset(vis,0,sizeof(vis));
int flow=dfs(S,INF);
res+=dis[S]*flow;
ans+=flow;
}
}
printf("%d %d",ans,res);
return 0;
}