0
点赞
收藏
分享

微信扫一扫

POJ 3228 二分最大流

题意:
      给你N个位置,每个位置都有金矿数量和仓库数量,然后位置和位置之间的距离给了出来,最后问你吧所有的金矿都放到库里面走的路径 最长的最短 是多少?

思路:
     比较简单的一个题,直接二分答案,然后用最大流是否满流来判断二分方向,还有就是建图的时候不用拆点什么的,一开始建图想麻烦了,都快敲完了才反应过来,具体看代码。

 

#include<stdio.h>

#include<string.h>

#include<queue>
#define N_node 200 + 10

#define N_edge 90000

#define INF 1000000000
using namespace std;
typedef struct

{

int to ,cost ,next;

}STAR;
typedef struct

{

int x ,t;

}DEP;
typedef struct

{

int a ,b ,c;

}EDGE;
EDGE edge[22000];

STAR E[N_edge];

DEP xin ,tou;

int list[N_node] ,list2[N_node] ,tot;

int deep[N_node];

int aaa[220] ,bbb[220];
void add(int a ,int b ,int c)

{

E[++tot].to = b;

E[tot].cost = c;

E[tot].next = list[a];

list[a] = tot;



E[++tot].to = a;

E[tot].cost = c;

E[tot].next = list[b];

list[b] = tot;

}
bool BFS_Deep(int s ,int t ,int n)

{

memset(deep ,255 ,sizeof(deep));

xin.x = s ,xin.t = 0;

deep[xin.x] = xin.t;

queue<DEP>q;

q.push(xin);

while(!q.empty())

{

tou = q.front();

q.pop();

for(int k = list[tou.x] ;k ;k = E[k].next)

{

xin.x = E[k].to;

xin.t = tou.t + 1;

if(deep[xin.x] != -1 || !E[k].cost)

continue;

deep[xin.x] = xin.t;

q.push(xin);

}

}

for(int i = 0 ;i <= n ;i ++)

list2[i] = list[i];

return deep[t] != -1;

}
int minn(int x ,int y)

{

return x < y ? x : y;

}
int DFS_Flow(int s ,int t ,int flow)

{

if(s == t) return flow;

int nowflow = 0;

for(int k = list2[s] ;k ;k = E[k].next)

{

list2[s] = k;

int to = E[k].to;

if(deep[to] != deep[s] + 1 || !E[k].cost)

continue;

int tmp = DFS_Flow(to ,t ,minn(E[k].cost ,flow - nowflow));

nowflow += tmp;

E[k].cost -= tmp;

E[k^1].cost += tmp;

if(nowflow == flow) break;

}

if(!nowflow) deep[s] = 0;

return nowflow;

}
int DINIC(int s ,int t ,int n)

{

int Ans = 0;

while(BFS_Deep(s ,t ,n))

{

Ans += DFS_Flow(s ,t ,INF);

}

return Ans;

}
bool ok(int n ,int m ,int sum ,int mid)

{

memset(list ,0 ,sizeof(list)) ,tot = 1;

for(int i = 1 ;i <= n ;i ++)

{

add(0 ,i ,aaa[i]);

add(i ,n + 1 ,bbb[i]);

}

for(int i = 1 ;i <= m ;i ++)

if(edge[i].c <= mid)

{

add(edge[i].a ,edge[i].b ,INF);

}

int flow = DINIC(0 ,n + 1 ,n + 1);

return flow == sum;

}



int main ()

{

int n ,m ,i ,sum;

while(~scanf("%d" ,&n) && n)

{

for(sum = 0 ,i = 1 ;i <= n ;i ++)

{

scanf("%d" ,&aaa[i]);

sum += aaa[i];

}

for(i = 1 ;i <= n ;i ++)

scanf("%d" ,&bbb[i]);

scanf("%d" ,&m);

for(i = 1 ;i <= m ;i ++)

scanf("%d %d %d" ,&edge[i].a ,&edge[i].b ,&edge[i].c);

int low ,up ,mid ,Ans = -1;

low = 0 ,up = 11000;

while(low <= up)

{

mid = (low + up) >> 1;

if(ok(n ,m ,sum ,mid))

{

Ans = mid;

up = mid - 1;

}

else low = mid + 1;

}

Ans == -1 ? puts("No Solution"):printf("%d\n" ,Ans);

}

return 0;

}

 

       
       

 


举报

相关推荐

0 条评论