问题描述:找从源点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
【我就直接贴过来啦~
将边拆开是为了用网络流,拆完的边是有向边