您的位置:首页 > 其它

HDU1532(最大流模版题ek/dinic/isap)

2015-08-26 19:29 477 查看
就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络水沟,并且聪明的约翰还控制了水的流速,本题就是让你求出最大流速,无疑要运用到求最大流了。题中N为水沟数,M为水沟的顶点,接下来Si,Ei,Ci分别是水沟的起点,终点以及其容量。求源点1到终点M的最大流速。

ek:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define M 205
#define inf 1e8
int n,m,a,b,c,g[M][M],flow[M],pre[M];
bool vis[M];
int bfs()
{
memset(vis,false,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(int i=1;i<=n;i++)
flow[i]=inf;
vis[1]=true;
queue<int>q;
q.push(1);
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
if(!vis[i]&&g[p][i]>0)
{
vis[i]=true;
flow[i]=min(flow[p],g[p][i]);
pre[i]=p;
q.push(i);
}
}
}
if(!vis
||n==1) return -1;
return flow
;
}
int ek()
{
int maxflow=0,d,res,temp;
while((d=bfs())!=-1)
{
maxflow+=d;
temp=n;
while(temp!=1)
{
res=pre[temp];
g[res][temp]-=d;
g[temp][res]+=d;
temp=res;
}
}
return maxflow;
}
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&m,&n))
{
memset(g,0,sizeof(g));
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
g[a][b]+=c;
}
printf("%d\n",ek());
}
return 0;
}


dinic:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define M 205
#define inf 1e8
int n,m,dis[M],r,cur[M];
struct edge
{
int u,v,cap;
edge(){}
edge(int a,int b,int c){u=a;v=b;cap=c;}
}eg[M*2];
vector<int>g[M];
void addedge(int a,int b,int c)
{
g[a].push_back(r);
eg[r++]=edge(a,b,c);
g[b].push_back(r);
eg[r++]=edge(b,a,0);
}
bool bfs()
{
memset(dis,0,sizeof(dis));
dis[1]=1;
queue<int>q;
q.push(1);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<g[x].size();i++)
{
edge &e=eg[g[x][i]];
if(!dis[e.v]&&e.cap>0)
{
dis[e.v]=dis[x]+1;
q.push(e.v);
}
}
}
return dis
;
}
int dfs(int x,int low)
{
if(x==n||!low) return low;
int p;
for(int i=cur[x];i<g[x].size();i++)
{
cur[x]=i;
edge &e=eg[g[x][i]];
if(e.cap>0&&dis[e.v]==dis[x]+1&&(p=dfs(e.v,min(low,e.cap))))
{
e.cap-=p;
eg[g[x][i]^1].cap+=p;
return p;
}
}
return 0;
}
void dinic()
{
int ans=0,now;
while(bfs())
{
memset(cur,0,sizeof(cur));
while(now=dfs(1,inf)) ans+=now;
}
printf("%d\n",ans);
}
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&m,&n))
{
int a,b,c;
r=0;
for(int i=1;i<=n;i++)
g[i].clear();
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
dinic();
}
return 0;
}


isap:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
#include <vector>
#include <algorithm>
#include <limits.h>
using namespace std;
#define inf 1e8
#define maxm 400000
#define maxn 1100
int head[maxn],eid;
int dis[maxn];//残量网络中节点i到汇点t的最短距离
int num[maxn];//和t的最短距离等于i的节点数量
int cur[maxn];//当前弧下标
int pre[maxn];//可增广路上的上一条弧的编号
struct node
{
int v,cap,next;
} edge[maxm];
void add(int u,int v,int cap)
{
edge[eid].v=v;
edge[eid].cap=cap;
edge[eid].next=head[u];
head[u]=eid++;
edge[eid].v=u;
edge[eid].cap=0;
edge[eid].next=head[v];
head[v]=eid++;
}
void bfs(int source,int sink)//预处理,利用反向BFS,更新dis数组
{
queue<int>q;
while(!q.empty()) q.pop();
memset(num,0,sizeof(num));
memset(dis,-1,sizeof(dis));
q.push(sink);
dis[sink]=0;
num[0]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
if(dis[v]==-1)
{
dis[v]=dis[u]+1;//找允许弧
num[dis[v]]++;
q.push(v);
}
}
}
}
int isap(int source,int sink,int n)//n为残量网络中的节点到汇点的最大距离,通常节点的个数,即上限
{
memcpy(cur,head,sizeof(cur));
int flow=0,u=pre[source]=source;
bfs(source,sink);//更新dis数组
while(dis[source]<n)
{
if(u==sink)
{
int df=inf,pos;
for(int i=source;i!=sink;i=edge[cur[i]].v)//追踪增广路路径,最小残量df
{
if(df>edge[cur[i]].cap)
{
df=edge[cur[i]].cap;
pos=i;
}
}
for(int i=source;i!=sink;i=edge[cur[i]].v)//更新流量
{
edge[cur[i]].cap-=df;
edge[cur[i]^1].cap+=df;
}
flow+=df;
u=pos;
}
int st;
for(st=cur[u];st!=-1;st=edge[st].next)//从当前弧开始查找允许弧
if(dis[edge[st].v]+1==dis[u]&&edge[st].cap)//找到允许弧跳出
break;
if(st!=-1)
{
cur[u]=st;
pre[edge[st].v]=u;
u=edge[st].v;
}
else
{
if((--num[dis[u]])==0) break;//GAP优化,出现断层结束
int mind=n;
for(int id=head[u];id!=-1;id=edge[id].next)//retreat操作:更新dis数组
{
if(mind>dis[edge[id].v]&&edge[id].cap)
{
cur[u]=id;//修改标号的同时修改当前弧
mind=dis[edge[id].v];
}
}
dis[u]=mind+1;
num[dis[u]]++;
if(u!=source) u=pre[u];// 回溯继续寻找允许弧
}
}
return flow;
}
void init()
{
memset(head,-1,sizeof(head));
eid=0;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m,a,b,c;
while(~scanf("%d%d",&m,&n))
{
init();
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
printf("%d\n",isap(1,n,n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: