xiebh 发表于 2013-1-27 05:23:29

最大流(转)

http://yuanhuixie.blogcn.com/

    流网络G=(V,E)是一个有向图,每一条边都有一非负容量 c(u,v)>=0.流网络中有两个特殊的点:源点 s 和汇点 t 。
   最大流问题中,给出一个具有源点和汇点的流网络,希望找出从源点到汇点的最大值流。
   解决最大流问题的 Ford-Fulkerson 方法依赖于三种重要的思想:残留网络、增广路径和割。
   Ford-Fulkerson是一种迭代的方法,通过更新有边相连的每对顶点 u,v之间的网络流 f,来计算出图 G=(V,E)中的最大流。

   class Link    {      public int key;      public int c;      public Link next;      public int Key      {            get            { return key; }            set            { key = value; }      }      public int C      {            get            { return c; }            set            { c = value; }      }      public Link Next      {            get            { return next; }            set            { next = value; }      }      public Link()      {            key = 0;            c = 0;            next = null;      }      public int Min()//返回残余容量      {            Link R=this.Next;            int min = this.C;            while (R != null)            {                if (min > R.C)                  min = R.C;                R = R.Next;            }            return min;      }         }   public int[,] Ford_Fulkerson(int[,] G, int s, int t)      {            int c = 0;            Link P = new Link();   //P用于表示图 G 的一条增广路径。            int[,] f = new int;            for(int i=0;i<G.Length;i++)                for (int j = 0; j < G.Length; j++)                {                  if (G != 0)//如果(u,v)是图G的边,把那条边的流值初始化为0                  {                        f = 0;                        f = 0;                  }                }            while ((P = ExistPath(G))!=null)//这里判断图 G中是否有残余流网络,此函数可以用广度优先搜索,但是我还是没写好            {                c = P.Min(); //取出增广路径的残余容量 c                while(P.Next!=null)                {                  f += c;                  f = 0 - f;                  P = P.Next;                }            }            return f;      }



昨天写了最大流里面的 Ford-Fulkerson 算法,但是里面有个寻找函数 ExistPath(int[,] G, int s, int t, int[,] f)我没写出来,今天写好了,现在再发一次:


   public int[,] Ford_Fulkerson(int[,] G, int s, int t)      {            int c = 0;            Link P = new Link();   //P用于表示图 G 的一条增广路径。            int[,] f = new int;            for (int i = 0; i < G.Length; i++)                for (int j = 0; j < G.Length; j++)                {                  if (G != 0)//如果(u,v)是图G的边,把那条边的流值初始化为0                  {                        f = 0;                        f = 0;                  }                }            while ((P = ExistPath(G, s, t, f)) != null)//这里判断图 G中是否有残余流网络,返回增广路径            {                c = P.Min(); //取出增广路径的残余容量 c                while (P.Next != null)                {                  f += c;                  f = 0 - f;                  P = P.Next;                }            }            return f;      }      public Link ExistPath(int[,] G, int s, int t, int[,] f)      {            int j = s, k = 0, Next = 0;            int[] Pass = new int;            for (int i = 0; i < G.Length; i++)                Pass = -1;            Pass = s;    //用 Pass[] 记下遍历过程中经过的节点的顺序            Link L2 = new Link();            Link L = L2;            for (int i = 0; i < G.Length; i++)            {                if ((Next = NextNode(G, Pass, j)) != -1)                  Pass = Next;                j = Next;                if (Next == t)//当到达汇点时就停止                  break;            }            for (int i = 0; i < G.Length; i++)            {                L2.Key = Pass;                L2 = L2.Next;                if (Pass == t)//当搜索过程中有到达汇点的就表示存在有增广路径                {                  L2.Key = Pass;                  return L;                }            }            return null;      }      public int NextNode(int[,] G, int[,] Pass, int j)      {            for (int i = 0; i < G.Length; i++)            {                if (Pass == -1)   //当节点没有被经过                {                  if (G != 0 && f != G)//当边(j,i)存在 且有残余容量时                  {                        return i;                  }                }            }            return -1;      }
页: [1]
查看完整版本: 最大流(转)