您的位置:首页 > 其它

hdu 1532 dinic 递归 与 非递归实现

2010-08-25 22:09 489 查看
//第一次学会用i^1 比如 i = 0 i^1 = 1 ;i = 1 i^1 = 0 ; i = 2 i^1 = 3 ; i = 3 i^1 = 2
//用来建反边很有用
/*inline Edge* reserve( Edge* p ){

return tb+ ((p-tb)^1);
}
*/ //返回零接表的反向边地址 留着以后可能用到

//星号部分为非递归实现 dfs 效率比递归更高 参照文献

//http://www.nocow.cn/index.php/Dinic
#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
#define INF 0x7f7f7f7
using namespace std;
const int V = 205;
const int E = 410;
struct Edge{
int u,v,c;
int next;
}edg[E];
int head[V],e,dis[V],src;
int stack[205],cur[205]; // 非递归
int n,m;
inline void addedge(int u,int v,int c)
{
edg[e].u = u; edg[e].v = v; edg[e].c = c;
edg[e].next = head[u];
head[u] = e++;
}
bool bfs()
{
queue<int>q;
int i,now,v,c;
memset(dis,-1,sizeof(dis));
dis[src] = 0;
q.push(src);
while(!q.empty())
{
now = q.front();
q.pop();
for(i = head[now]; i != -1; i = edg[i].next)
{
v = edg[i].v;
c = edg[i].c;
if(dis[v] == -1 && c > 0)
{
dis[v] = dis[now] + 1;
q.push(v);
}
}
}
return (dis
>= 0);
}
int dfs(int now,int minf)
{
if(now == n)return minf;
int v,i,c,tf,t;
for(i = head[now]; i != -1; i = edg[i].next)
{
v = edg[i].v;
c = edg[i].c;
if(dis[v] == dis[now] + 1 && c > 0)
{
t = min(c,minf);
if( ( tf = dfs(v,t) ) > 0)
{
edg[i].c -= tf;
edg[i^1].c += tf; //反向边加回流量
return tf;
}
}
}
return 0;
}
/* 非递归实现 利用栈
int dinic_dfs()
{
int top=0,e,v,i;
int ret = 0;
int u=src;
// memcpy(cur,head,sizeof(cur));
while(1)
{
if(u == n)
{
int min=-1,tf = INT_MAX;
for(i=0; i < top; ++i)
{
e = stack[i];
if(edg[e].c < tf)
{
tf = edg[e].c;
min=i;
}
}
for(i=0;i < top;++i)
{
e = stack[i];
edg[e].c -= tf;
edg[e^1].c += tf;
}
ret += tf;
top = min; //返回至饱和边 这样可以
u = edg[stack[top]].u; //获得 源点能够到达的最后一个顶点 减少搜索次数
}
for(i = head[u];i != -1;i = edg[i].next)
{
v = edg[i].v;
if(dis[u]+1 == dis[v] && edg[i].c > 0)
break;
}
// cur[u]=i; //类似于优化 从已经搜索过的边开始搜索 上面这个for循环改成 i = cur[u]
if(i != -1)
{
stack[top++]=i;
u = edg[i].v;
}
else
{
if(top==0)break;
dis[u]=-1;
--top;
u = edg[stack[top]].u;
}
}
return ret;
}
*/
int dinic()
{
int ret = 0,t;
while(bfs())
{
t = dfs(1,INF);
if(t)
ret += t;
}
return ret;
}
void Init()
{
int i,s,t,c;
memset(head,-1,sizeof(head));
e = 0;src = 1;
for(i = 1; i <= m; i++)
{
scanf("%d %d %d",&s,&t,&c);
addedge(s,t,c);
addedge(t,s,0);//建为0的反边
}
printf("%d/n",dinic());
}
int main()
{
while(scanf("%d %d",&m,&n) != EOF)
{
Init();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: