网络流初步

问题描述:找从源点s到汇点t能流过的最大流量

最大流问题

Ednonds-Karp

每次增广的时候用BFS,这样不用找所有可能增加的流量,减少了循环次数。

复杂度 O(VE^2) 适用于几百的数据,可以直接用邻接矩阵存储,要存反向边

poj1273

 注意两个顶点间可能有多条边,相加即可,这也是邻接矩阵的好处

   cap[][]表示初始的容量

   flow[][]表示当前增广的流量

  q是BFS的队列啦 orz...

   注意队列的操作,多组数据每次队列要清空的话只要在EK()过程中重新申明就好了

   读入的时候好坑啊,要么 while(scanf("%d%d", &m, &n)!=EOF)  要么 while (cin>>m>>n)

   

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 210
#define INF 0x7fffffff
int ansf,n,m,x,y,z;
int cap[MAXN][MAXN],flow[MAXN][MAXN],pre[MAXN],dis[MAXN];
void add(int x,int y,int z)
{
    cap[x][y]+=z;
}
int EK(int s,int t)
{
   queue<int> q;
   memset(flow,0,sizeof(flow));
   ansf=0;
   for (;;) //新技能get啦~  要不断从源点到汇点
   {
       memset(dis,0,sizeof(dis));//存从s走过来可以流经的最大流量
       dis[s]=INF;
       q.push(s);
       while (!q.empty())
       {
           int u=q.front();q.pop();
           for (int v=1;v<=n;v++)//邻接矩阵
            if (!dis[v] && cap[u][v]>flow[u][v])//dis[v]==0表示没有访问过,注意这里不是>=,如果是>=,尽管dis变成0,也会不停地向queue中加节点,死循环=w=
           {
             pre[v]=u;//修改流的时候要往前走
             q.push(v);
             dis[v]=min(dis[u],cap[u][v]-flow[u][v]);
           }
       }
       if (dis[t]==0) break;
       //更新流量
       for (int v=t;v!=s;v=pre[v])
       {
           flow[pre[v]][v]+=dis[t];
           flow[v][pre[v]]-=dis[t];//反向边使得可以流回去
       }
       ansf+=dis[t];
   }
   return ansf;
}
int main()
{
    while (scanf("%d%d", &m, &n)!=EOF)
    {
          memset(cap,0,sizeof(cap));
          for (int i=1;i<=m;i++)
          {
              scanf("%d%d%d", &x, &y, &z);
              add(x,y,z);
          }
          //Edmonds-Karp
          printf("%d\n", EK(1,n));
    }
    return 0;
}


无向图的连通度:

     指在图中删去最少的边或点,使得图中指定的两个点s和t,不连通

    这个最小的数就是无向图的连通度

    无向图的连通度分为点连通度和边连通度

    poj1966

   题意:给一张无向图,求点连通度

    n=50

   n^2枚举s和t

   【我就直接贴过来啦~

  1. 【1】有向图的边连通度: 
  2. 这个其实就是最小割问题。以s为源点,t为汇点建立网络,原图中的每条边在网络中仍存在,容量为1, 
  3. 求该网络的最小割(也就是最大流)的值即为原图的边连通度。 
  4. 【2】有向图的点连通度: 
  5. 需要拆点。建立一个网络,原图中的每个点i在网络中拆成i'与i'',有一条边<i', i''>,容量为1 
  6. (<s', s''>和<t', t''>例外,容量为正无穷)。原图中的每条边<i, j>在网络中为边<i'', j'>, 
  7. 容量为正无穷。以s'为源点、t''为汇点求最大流,最大流的值即为原图的点连通度。 
  8. 说明:最大流对应的是最小割。显然,容量为正无穷的边不可能通过最小割,也就是原图中的边和s、t两个点 
  9. 不能删去;若边<i, i''>通过最小割,则表示将原图中的点i删去。 
  10. 【3】无向图的边连通度: 
  11. 将图中的每条边(i, j)拆成<i, j>和<j, i>两条边,再按照有向图的办法(【1】)处理; 
  12. 【4】无向图的点连通度: 
  13. 将图中的每条边(i, j)拆成<i, j>和<j, i>两条边,再按照有向图的办法(【2】)处理。 

          将边拆开是为了用网络流,拆完的边是有向边


你可能感兴趣的:(Queue,poj,图论,DFS,网络流)