您的位置:首页 > 大数据 > 人工智能

poj 1273Drainage Ditches

2014-03-09 21:26 204 查看
最大流

#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
const int MAXN=20010;//点数的最大值
const int MAXM=880010;//边数的最大值
const int INF=0x3f3f3f3f;

struct Node
{
int from,to,next;
int cap;
}edge[MAXM];
int tol;
int head[MAXN];
int dis[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dis[i]==x的个数为y

int n;//n是总的点的个数,包括源点和汇点

void init()
{
//tol 记录添加的总边数
tol=0;
memset(head, -1, sizeof(head));
}
void addedge(int u,int v,int w)
{
//添加前向边
//from u to v
edge[tol].from = u;
edge[tol].to = v;
edge[tol].cap = w;
edge[tol].next = head[u];
head[u] = tol++;

//添加后向边
edge[tol].from = v;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
void BFS(int start,int end)
{
memset(dis, -1, sizeof(dis));
memset(gap, 0, sizeof(gap));
gap[0] = 1;
dis[end] = 0;
int queue[MAXN];
int front, rear;
front = rear = 0;
queue[rear++] = end;			//这里应该是s吧????
//front 和 rear +1之后都需要判断一下是否等于maxn, 如果是则front 或 rear = 0
while(front != rear)
{
int u = queue[front++];
if(front == MAXN)
front = 0;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(dis[v] != -1)		//表示已标记过
continue;
queue[rear++] = v;
if(rear == MAXN)
rear = 0;
dis[v] = dis[u]+1;
++gap[dis[v]];			//距离为dis[v]的点的个数
}
}
}
int SAP(int start,int end)
{
int res = 0;			//存储距离
//用bfs绘制距离图
BFS(start, end);
int cur[MAXN];			//存储一条弧
int pre[MAXN];
int top = 0;			// top是当前增广路中最前面一个点。
//将head存储的最后一条弧作为初始弧,在此基础上寻找增广边
memcpy(cur, head, sizeof(head));
int u = start;
int i;
while(dis[start] < n)
{
if(u == end)			//如果找到了一个流,则在剩余网络中查找增广路
{
int temp = INF;
int inser;
//寻找一条增广路,并记录下最小的权值
for(i = 0; i < top; i++)
if(temp > edge[pre[i]].cap)
{
temp = edge[pre[i]].cap;
inser = i;
}
//前向边全部-temp, 后向边+temp
for(i = 0; i < top; i++)
{
edge[pre[i]].cap -= temp;
edge[pre[i]^1].cap += temp;
}
res += temp;
top = inser;
u = edge[pre[top]].from;
}

if(u != end && gap[dis[u]-1] == 0)//出现断层,无增广路
break;
//找到下一个编号
for(i = cur[u]; i != -1;i = edge[i].next)
if(edge[i].cap != 0 && dis[u] == dis[edge[i].to]+1)
break;

if(i != -1)				//如果没有找到容许弧
{
cur[u] = i;
pre[top++] = i;		//向pre中加了一条边,且
u = edge[i].to;
}
else					//如果找到容许弧
{
int min = n;
for(i = head[u]; i != -1; i = edge[i].next)
{
if(edge[i].cap == 0)
continue;
if(min > dis[edge[i].to])
{
min = dis[edge[i].to];
cur[u] = i;
}
}
--gap[dis[u]];
dis[u] = min+1;
++gap[dis[u]];
if(u != start)
u = edge[pre[--top]].from;
}
}
return res;
}
int main(void)
{
//    freopen("1.txt", "r", stdin);
int m;
while(cin>>m>>n)
{
tol = 0;
memset(head, -1, sizeof(head));
for(int i = 0;i < m;i++)
{
int a, b, c;
cin>>a>>b>>c;
addedge(a, b, c);
}
cout<<SAP(1, n)<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: