hdu 1532 dinic 递归 与 非递归实现

来源:互联网 发布:李蛋女朋友淘宝店 编辑:程序博客网 时间:2024/05/29 15:25

//第一次学会用i^1 比如 i = 0 i^1 = 1  ;i = 1 i^1 = 0 ; i = 2 i^1 = 3 ; i = 3 i^1 = 2
//用来建反边很有用
/*inline Edge*  reserve( Edge* p ){

    return tb+ ((p-tb)^1);
}
*/ //返回零接表的反向边地址 留着以后可能用到

//星号部分为非递归实现 dfs  效率比递归更高 参照文献

//http://www.nocow.cn/index.php/Dinic
#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
#define INF 0x7f7f7f7
using namespace std;
const int V = 205;
const int E = 410;
struct Edge{
 int u,v,c;
 int next;
}edg[E];
int head[V],e,dis[V],src;
int stack[205],cur[205]; // 非递归
int n,m;
inline void addedge(int u,int v,int c)
{
 edg[e].u = u; edg[e].v = v; edg[e].c = c;
 edg[e].next = head[u];
  head[u] = e++;
}
bool bfs()
{
 queue<int>q;
 int i,now,v,c;
 memset(dis,-1,sizeof(dis));
 dis[src] = 0;
 q.push(src);
 while(!q.empty())
 {
  now = q.front();
  q.pop();
  for(i = head[now]; i != -1; i = edg[i].next)
  {
   v = edg[i].v;
   c = edg[i].c;
   if(dis[v] == -1 && c > 0)
   {
    dis[v] = dis[now] + 1;
    q.push(v);
   }
  }
 }
 return (dis[n] >= 0);
}
int dfs(int now,int minf)
{
 if(now == n)return minf;
 int v,i,c,tf,t;
 for(i = head[now]; i != -1; i = edg[i].next)
 {
  v = edg[i].v;
  c = edg[i].c;
  if(dis[v] == dis[now] + 1 && c > 0)
  {
   t = min(c,minf);
   if( ( tf = dfs(v,t) ) > 0)
   {
    edg[i].c -= tf;
    edg[i^1].c += tf;      //反向边加回流量
    return tf;
   }
  }
 }
 return 0;
}
/*         非递归实现 利用栈
int dinic_dfs()
{
 int top=0,e,v,i;
 int ret = 0;
 int u=src;
 // memcpy(cur,head,sizeof(cur));
 while(1)
 {
    if(u == n)
  {
            int min=-1,tf = INT_MAX;
            for(i=0; i < top; ++i)
   {
    e = stack[i];
       if(edg[e].c < tf)
    {
        tf = edg[e].c;
        min=i;
       }
      }
        for(i=0;i < top;++i)
   {
    e = stack[i];
       edg[e].c -= tf;
               edg[e^1].c += tf;
      }
      ret += tf;
      top = min;     //返回至饱和边 这样可以
      u = edg[stack[top]].u;     //获得 源点能够到达的最后一个顶点 减少搜索次数
       }
       for(i = head[u];i != -1;i = edg[i].next)
  {
     v = edg[i].v;
     if(dis[u]+1 == dis[v] && edg[i].c > 0)
     break;
    }
    // cur[u]=i;       //类似于优化 从已经搜索过的边开始搜索  上面这个for循环改成 i = cur[u]
      if(i != -1)
  {
     stack[top++]=i;
       u = edg[i].v;
        }
        else
  {
     if(top==0)break;
            dis[u]=-1;
            --top;
            u = edg[stack[top]].u;
    }
 }
 return ret;
}
*/
int dinic()
{
 int ret = 0,t;
 while(bfs())
 {
  t = dfs(1,INF);
  if(t)
  ret += t;
 }
 return ret;
}
void Init()
{
 int i,s,t,c;
 memset(head,-1,sizeof(head));
 e = 0;src = 1;
 for(i = 1; i <= m; i++)
 {
  scanf("%d %d %d",&s,&t,&c);
  addedge(s,t,c);
  addedge(t,s,0);//建为0的反边
 }
 printf("%d/n",dinic());
}
int main()
{
 while(scanf("%d %d",&m,&n) != EOF)
 {
  Init();
 }
 return 0;
}

原创粉丝点击