您的位置:首页 > 理论基础 > 计算机网络

TOJ 1684. Power Network 【第一道网络流 】

2010-07-25 21:52 351 查看
/* 第一道网络流。。。dinic做的,参考了别人程序。

* dinic之所以比较高效是因为它在BFS的时候给每个点赋了一个层次值,所以在每次寻找增广路进行增流的时候,

* 可以顺着层次值递增进行,到达汇点以后可以回溯到某个可以继续增广的点继续增流直到找不到一条增广路,有效

* 的利用了BFS所得到的信息。

* 使用list的迭代器记录某次增流后残留量为0的点,便于进行回溯

*/

#include <cstdio>
#include <cstring>
#include <queue>
#include <list>
#define INF 0x1f1f1f1f
#define MAXN 205
using namespace std;
int n,m,nsrc,nsink;
int src,sink;
int restflow[MAXN][MAXN],level[MAXN];//残留网络的邻接矩阵,level数组记录层次
bool flag[MAXN];
inline void add_edge(int u,int v,int w){
restflow[u][v] = w;
}
inline void initial(){      // input  and initialize
char temp[500];
n += 2;  //增加两个超级点
memset(restflow,0,sizeof(restflow));
src = 1; sink = n;
int i,st,ed,w;
for(i = 1;i <= m; ++i){
scanf("%s",temp);
sscanf(temp,"(%d,%d)%d",&st,&ed,&w);
add_edge(st+2,ed+2,w);
}
for(i = 1;i <= nsrc; ++i){
scanf("%s",temp);
sscanf(temp,"(%d)%d",&ed,&w);
add_edge(1,ed+2,w);
}
for(i = 1;i <= nsink; ++i){
scanf("%s",temp);
sscanf(temp,"(%d)%d",&st,&w);
add_edge(st+2,n,w);
}
}
inline int hasflow(int x){
for(int i = 1;i <= n; ++i)
if(restflow[x][i] && level[i] == level[x] + 1)
return i;
return 0;
}
inline bool BFS(){
queue<int>que;
while(!que.empty()) que.pop();
bool mark = false;
memset(flag,false,sizeof(flag));
for(int i = 1;i <= n; i++)
level[i] = INF;
que.push(src);
flag[src] = true;
level[src] = 0;
while(!que.empty()){
int tep = que.front();
que.pop();
for(int i = 1;i <= n; ++i){
if(!flag[i] && restflow[tep][i] != 0){
flag[i] = true;
level[i] = level[tep] + 1;
que.push(i);
}
}
if(tep == sink) mark = true;
}
return mark;
}
inline int dinic(){
int u,v,capflow,last,maxflow = 0;
list<int>path;
list<int>::iterator its;
while(BFS()){
path.clear();
path.push_back(src);
while(hasflow(src) != 0){
u = path.back();
if(u != sink){
if(v = hasflow(u))     //可增广
path.push_back(v);
else{
path.pop_back();
level[u] = INF;
}
}else{
capflow = INF;
for(its = path.begin(); its != path.end(); ++its){
u = *its;
if((++its) == path.end()) break;
v = *its;
if(restflow[u][v] < capflow)
capflow = restflow[u][v];
--its;
}
last = -1;
maxflow += capflow;
for(its = path.begin(); its != path.end(); ++its){
u = *its;
if((++its) == path.end() ) break;
v = *its;
restflow[u][v] -= capflow;
if(restflow[u][v] == 0 && last == -1)
last = u;
--its;
}
while(path.back() != last ) path.pop_back();  //等价于回溯到可增广的点,在新的循环里继续增流
}
}
}
return maxflow;
}
int main()
{
while(scanf("%d%d%d%d",&n,&nsrc,&nsink,&m) != EOF){
initial();
printf("%d/n",dinic());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: