【图】Dinic(n^2m)

来源:互联网 发布:java解压缩gz文件 编辑:程序博客网 时间:2024/05/01 15:51
struct Edge{int from,to,cap,flow;void AddEdge(int from,int to,int cap){edges.push_back((Edge){from,to,cap,0});edges.push_back((Edge){to,from,0,0}});m=edges.size();G[from].push_back(m-2);G[to].push_back(m-1);}};struct Dinic{int n,m,s,t;vector<Edge> edges;vector<int> G[maxn];bool vis[maxn];int d[maxn];int cur[maxn];bool BFS(){memset(vis,0,sizeof(vis));queue<int> Q;Q.push(s);d[s]=0;vis[s]=1;while(!Q.empty()){int x=Q.front(); Q.pop();for(int i=0;i<G[x].size();i++){Edge& e=edges[G[x][i]];if(!vis[e.to] && e.cap>e.flow){vis[e.to]=1;d[e.to]=d[x]+1;Q.push(e.to);}}}return vis[t];}int DFS(int x,int a){if(x==t || a==0)return a;int flow=0,f;for(int& i=cur[x];i<G[x].size();i++){Edge& e=edges[G[x][i]];if( d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0 ){e.flow+=f;edges[G[x][i]^1].flow-=f;flow+=f;a-=f;if(a==0)break;}}return flow;}int Maxflow(int s,int t){this->s=s,this->t=t;int flow=0;while(BFS()){memset(cur,0,sizeof(cur));flow+=DFS(s,INF);}return flow;}};

伪代码

下面是dfs的过程:
[c-sharp] view plaincopy
  1. ps;  
  2. While outdegree(s)>0  
  3.     up.top;  
  4.     if u<>t  
  5.         if outdegree(u)>0  
  6.             设(u,v)为层次图中的一条边;  
  7.             pp,v;     
  8.         else  
  9.             从p和层次图中删除点u,  
  10.             以及和u连接的所有边;  
  11.     else  
  12.         增广p(删除了p中的饱和边);  
  13.         令p.top为p中从s可到达的最后顶点;  
  14. end while  

在程序里,p表示找到的增广路径,p.top为路径中的最后一个顶点。一开始,p中只有源点。

整个While循环分为2个操作。如果p的最后一个顶点为汇点,也就是说找到了增广路,那么对p增广,注意到增广后一定有一条或多条p中的边被删除了。这时,我们使增广路径后退至p中从源点可到达的最后一个顶点。

如果p的最后一个顶点不为汇点,那么观察最后那个的顶点u 。若在层次图中存在从u连出的一条边,比如(u,v),我们就将顶点v放入路径p中,继续dfs遍历;否则,点u对之后的dfs遍历就没有用了,我们将点u以及层次图中连到u的所有边删除,并且在p中后退一个点。

Dfs过程将会不断重复这2个操作,直到从源点连出的边全部被删除为止。


nocow

bool build()//建立层次图{int x,y;memset(d,-1,sizeof(d));memset(G,-1,sizeof(G));bg=ed=d[s]=0;Q[ed++]=s;G[s]=g[s];while(bg<ed){x=Q[bg++];for(int i=g[x];i+1;i=np[i]){y=to[i];if(cap[i]&&d[y]==-1){d[y]=d[x]+1;G[y]=g[y];if(y==t)return true;Q[ed++]=y;}}}return false;} int find(int x,int low=inf)//进行增广{if(x==t)return low;int ret=0,y;for(int &i=G[x];i+1;i=np[i])//注意i是引用{y=to[i];if(cap[i] && d[y]==d[x]+1 && (ret=find(y,low<?cap[i]))){cap[i]-=ret;cap[vp[i]]+=ret;return ret;}}return 0;} int dinic()//主过程{int flow;while(build())while(flow=find(s))cnt+=flow;return 0;}

非递归

//Author: dd_engivoid Dinic(){    for(;;){        BFS();        if(D[T]==-1)break;        int path_n=0;        int x=S;        memcpy(cur,E,sizeof(cur));        for(;;){            if(x==T){                int mink=-1,delta=INT_MAX;                for(int i=0;i<path_n;++i){                    if(path[i]->c<delta){                        delta=path[i]->c;                        mink=i;                    }                }                for(int i=0;i<path_n;++i){                    path[i]->c-=delta;                    path[i]->back->c+=delta;                }                path_n=mink;                x=path[path_n]->x;            }            edge* e;            for(e=cur[x];e;e=e->next){                if(e->c==0)                    continue;                int y=e->y;                if(D[x]+1==D[y])                    break;            }            cur[x]=e;            if(e){                path[path_n++]=e;                x=e->y;            }            else{                if(path_n==0)                    break;                D[x]=-1;                --path_n;                x=path[path_n]->x;            }        }    }}


0 0