网络流
适用的图 :
注意上面的唯一性
满流:从源点出发的流量 等于 最大流(就是源点发出多少,汇点接受多少)
网络流建模问题:
因为网络流算法是基于有向图并且只有一个源点一个汇点的模型的
必要时候我们必须进行模型的转化
1.无向图转有向图:可以把,u,v之间的无向边变为(u,v),(v,u)两个?向边,容量一样。然后每个边再建立一个反向边,一共四条边。
u、v的实际流量为两者之差。
注:若原图是有向图,则两点之间的实际流量就是两点之间反向路径的权值
2.多个源点、多个汇点:建立一个超级源点,一个超级汇点,分别连接所有的源点和汇点,然后求从超级源点到超级汇点的最大流,新边权视情况而定
hdu 3549
AC 代码1(效率最高)
弧优化
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100010
using namespace std;
int point[maxn*2],next1[maxn*2],first[maxn*2],w[maxn*2];
int cur[maxn*2];
int dis[maxn];
int q[maxn];
int n,m,ans,k;
bool bfs();
int dfs(int,int);
int main()
{
int T ,cnt = 0;
cin>>T;
while( T--)
{
cnt++;
k = 0;
memset(point,0xff,sizeof(point));
memset(next1,0xff,sizeof(next1));
memset(first,0xff,sizeof(first));//0xff 表示 - 1
scanf("%d%d",&n,&m);
for(int i = 1,u,v,val; i <= m; i++)
{
scanf("%d%d%d",&u,&v,&val);
point[k] = v;next1[k] = first[u];first[u] = k;w[k++] = val;
point[k] = u;next1[k] = first[v];first[v] = k;;w[k++] = 0;
}
ans = 0;
while(bfs())
{
int tmp = 0;
while( tmp = dfs(1,0x7fffffff))
ans += tmp;
}
printf("Case %d: %d\n",cnt,ans);
memset(w,0,sizeof(w));
}
}
int dfs(int now,int low)
{
int tmp = 0;
if(now == n) return low;
for(int k = cur[now];k != -1;k = next1[k])
{
int new1 = point[k];
cur[now] = k;
if(dis[new1] == dis[now] + 1 && w[k] > 0 && (tmp = dfs(new1,min(low,w[k]))))
{
w[k] -= tmp;
w[k^1] += tmp;
return tmp;
}
}
return 0;
}
bool bfs()
{
int h,t;
for(int i = 1;i <= n; i++)
{
cur[i] = first[i];
dis[i] = -1;//-1
}
dis[1] = 0;
h = 0,t = 1;
q[1] = 1;
while(h < t)
{
int now = q[++h];
int k = first[now];
while(k != -1)
{
int new1 = point[k];
if(dis[new1] < 0 && w[k] > 0)
{
dis[new1] = dis[now] + 1;
q[++t] = new1;
}
k = next1[k];
}
}
return dis[n] > 0?1:0;
}
AC 代码2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100010
using namespace std;
int point[maxn*2],next1[maxn*2],first[maxn*2],w[maxn*2];
int dis[maxn];
int q[maxn];
int n,m,ans,k;
bool bfs();
int dfs(int,int);
int main()
{
int T ,cnt = 0;
cin>>T;
while( T--)
{
cnt++;
k = 0;
memset(point,0xff,sizeof(point));
memset(next1,0xff,sizeof(next1));
memset(first,0xff,sizeof(first));//0xff 表示 - 1
scanf("%d%d",&n,&m);
for(int i = 1,u,v,val; i <= m; i++)
{
scanf("%d%d%d",&u,&v,&val);
point[k] = v;next1[k] = first[u];first[u] = k;w[k++] = val;
point[k] = u;next1[k] = first[v];first[v] = k;w[k++] = 0;
}
ans = 0;
while(bfs())
{
int tmp = 0;
while( tmp = dfs(1,0x7fffffff))
ans += tmp;
}
printf("Case %d: %d\n",cnt,ans);
memset(w,0,sizeof(w));
}
}
int dfs(int now,int low)
{
int tmp = 0;
if(now == n) return low;
for(int k = first[now];k != -1;k = next1[k])
{
int new1 = point[k];
if(dis[new1] == dis[now] + 1 && w[k] > 0 && (tmp = dfs(new1,min(low,w[k]))))
{
w[k] -= tmp;
w[k^1] += tmp;
return tmp;
}
}
return 0;
}
bool bfs()
{
int h,t;
memset(dis,0xff,sizeof(dis));
dis[1] = 0;
h = 0,t = 1;
q[1] = 1;
while(h < t)
{
int now = q[++h];
int k = first[now];
while(k != -1)
{
int new1 = point[k];
if(dis[new1] < 0 && w[k] > 0)
{
dis[new1] = dis[now] + 1;
q[++t] = new1;
}
k = next1[k];
}
}
return dis[n] > 0?1:0;
}
AC代码3(效率最低)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100010
using namespace std;
int point[maxn*2],next1[maxn*2],first[maxn*2],w[maxn*2];
int dis[maxn];
int q[maxn];
int n,m,ans,k;
bool bfs();
int dfs(int,int);
int main()
{
int T ,cnt = 0;
cin>>T;
while( T--)
{
cnt++;
k = 0;
memset(point,0,sizeof(point));
memset(next1,0,sizeof(next1));
memset(first,0,sizeof(first));//0xff 表示 - 1
scanf("%d%d",&n,&m);
for(int i = 1,u,v,val; i <= m; i++)
{
scanf("%d%d%d",&u,&v,&val);
point[++k] = v;next1[k] = first[u];first[u] = k;w[k] = val;
point[++k] = u;next1[k] = first[v];first[v] = k;w[k] = 0;
}
ans = 0;
while(bfs())
{
int tmp = 0;
while( tmp = dfs(1,0x7fffffff))
ans += tmp;
}
printf("Case %d: %d\n",cnt,ans);
memset(w,0,sizeof(w));
}
}
int dfs(int now,int low)
{
int tmp = 0;
if(now == n) return low;
for(int k = first[now];k != 0;k = next1[k])
{
int new1 = point[k];
if(dis[new1] == dis[now] + 1 && w[k] > 0 && (tmp = dfs(new1,min(low,w[k]))))
{
w[k] -= tmp;
if(k % 2)
w[k + 1] += tmp;
else w[k - 1] += tmp;
return tmp;
}
}
return 0;
}
bool bfs()
{
int h,t;
memset(dis,0xff,sizeof(dis));
dis[1] = 0;
h = 0,t = 1;
q[1] = 1;
while(h < t)
{
int now = q[++h];
int k = first[now];
while(k != 0)
{
int new1 = point[k];
if(dis[new1] < 0 && w[k] > 0)
{
dis[new1] = dis[now] + 1;
q[++t] = new1;
}
k = next1[k];
}
}
return dis[n] > 0?1:0;
}