the reason of failure:
1、pre[i]=u而不是pre[u]=i
复杂度O(m*2n)
就是从第一个点开始找能到目的地点的这条线,然后在这条线找出最小的容量m,
然后将这条线上的所有边都减去m,然后反向+m,
再重复找从第一个点能到目的地点的路径,直到找不到路径。
输入样例:
5 4
1 2 1
1 3 1
2 3 1
3 4 1
2 4 1
事实上,当我们第二次的增广路走3-2这条反向边的时候,就相当于把2-3这条正向边已经是用了的流量给”退”了回去,不走2-3这条路,而改走从2点出发的其他的路也就是2-4。(有人问如果这里没有2-4怎么办,这时假如没有2-4这条路的话,最终这条增广路也不会存在,因为他根本不能走到汇点)同时本来在3-4上的流量由1-3-4这条路来”接管”。而最终2-3这条路正向流量1,反向流量1,等于没有流量。(也就是这条退回去的路其实可以不用走这两次也能达到终点)
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
int map1[500][500];
int pre[500];
bool walked[500];
int m;
int dfs(int a,int b){
queue<int>qq;
qq.push(a);
int i;
memset(walked,0,sizeof(walked));
memset(pre,-1,sizeof(pre));
pre[a]=a;
int u;
while(!qq.empty()){
// cout << 666 <<endl;
u=qq.front();qq.pop();
for(i=1;i<=m;i++)
if(map1[u][i]>0&&!walked[i]){
walked[i]=1;
pre[i]=u; //i的pre是u而不是u的pre是i
qq.push(i);
if(i==b)return true; //意思为能从a走到b
}
}
return false;
}
int result(int a,int b){
int g2=0,i;
while(dfs(a,b)){
int g1=99999;
for(i=b;i!=a;i=pre[i]){
g1=min(map1[pre[i]][i],g1);
}
for(i=b;i!=a;i=pre[i]){
map1[pre[i]][i]-=g1;
map1[i][pre[i]]+=g1;
}
g2+=g1;
}
return g2;
}
int main(){
freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3;
int n;
memset(map1,0,sizeof(map1));
cin >> n>>m;// 表明有n条边,有m个图
for(i=0;i<n;i++){
cin >> t1>> t2 >>t3;
map1[t1][t2]+=t3;
}
printf("%d",result(1,m));
return 0;
}
复习了一遍最大流,其实就是搜索找增广,找到以后g2+通过pre这条增广的最小流量的边,也就是这个增广可以走的流量,然后cup正向-,逆向+。
#include <queue>
#include<iostream>
#include<stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <ctime>
#include <queue>
using namespace std;
int const maxn=5e4+7;
struct ttt{
int l,r,m;
};
ttt tree[maxn*4];
int map1[550][550];
int cup[550][550];
int pre[550];
int vis[550];
int n;
int dfs(int a,int b){
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
queue<int>qq;
qq.push(a);
int u;
while(!qq.empty()){ //只用判断是否可以走
u=qq.front();qq.pop();
for(int i=1;i<=n;i++)
if(vis[i]==0&&cup[u][i]>0){
pre[i]=u;vis[i]=1;
qq.push(i);
if(i==b)return true;
}
}
return false;
}
int result(int a,int b){
int g2=0;
while(dfs(a,b)){ //从a开始dfs向b,直到不能dfs
int g1=1e9+7;
// cout <<a <<"到" <<b << endl;
for(int i=b;i!=a;i=pre[i])
g1=min(g1,cup[pre[i]][i]);
for(int i=b;i!=a;i=pre[i]){
cup[pre[i]][i]-=g1;
cup[i][pre[i]]+=g1;
}
g2+=g1; //g2是最大流
}
return g2;
}
int main(){
int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,m;
freopen("in.txt","r",stdin);
cin >> m>> n;
for(i=1;i<=m;i++){
cin >> t1>>t2>>t3;
cup[t1][t2]=t3;
}
cout << result(1,n) << endl;
return 0;
}
更快的模版Dinic
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int Ni = 210;
const int MAX = 1<<26;
struct Edge{
int u,v,c;
int next;
}edge[20*Ni];
int n,m;
int edn;//边数
int p[Ni];//父亲
int d[Ni];
int sp,tp;//原点,汇点
void addedge(int u,int v,int c)
{
edge[edn].u=u; edge[edn].v=v; edge[edn].c=c;
edge[edn].next=p[u]; p[u]=edn++;
edge[edn].u=v; edge[edn].v=u; edge[edn].c=0;
edge[edn].next=p[v]; p[v]=edn++;
}
int bfs()
{
queue <int> q;
memset(d,-1,sizeof(d));
d[sp]=0;
q.push(sp);
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=p[cur];i!=-1;i=edge[i].next)
{
int u=edge[i].v;
if(d[u]==-1 && edge[i].c>0)
{
d[u]=d[cur]+1;
q.push(u);
}
}
}
return d[tp] != -1;
}
int dfs(int a,int b)
{
int r=0;
if(a==tp)return b;
for(int i=p[a];i!=-1 && r<b;i=edge[i].next)
{
int u=edge[i].v;
if(edge[i].c>0 && d[u]==d[a]+1)
{
int x=min(edge[i].c,b-r);
x=dfs(u,x);
r+=x;
edge[i].c-=x;
edge[i^1].c+=x;
}
}
if(!r)d[a]=-2;
return r;
}
int dinic(int sp,int tp)
{
int total=0,t;
while(bfs())
{
while(t=dfs(sp,MAX))
total+=t;
}
return total;
}
int main()
{
freopen("in.txt","r",stdin);
int i,u,v,c;
while(~scanf("%d%d",&m,&n))
{
edn=0;//初始化
memset(p,-1,sizeof(p));
sp=1;tp=n;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
}
printf("%d\n",dinic(sp,tp));
}
return 0;
}