0
点赞
收藏
分享

微信扫一扫

POJ3228二分最大流

elvinyang 2022-07-27 阅读 28

题意:
      有n个点,每个点有两个权值,金子数量还有仓库容量,金子可以存在自己的仓库里或者是别的仓库里,仓库和仓库之间有距离,问所有金子都必须存到库里最大距离的最小是多少?


思路:
      比较简单,方法也不唯一,大体可以这样,先二分,然后用最大流或者匹配..来判断是不是满足就行了,我用的是二分最大流,具体代码在下面。


#include<queue>

#include<stdio.h>

#include<string.h>

#include<algorithm>



#define N_node 400 + 50

#define N_edge 200 * 200 * 2 + 10000

#define INF 1000000000



using namespace std;



typedef struct

{

int to ,cost ,next;

}STAR;



typedef struct

{

int a ,b ,c;

}EDGE;



typedef struct

{

int x ,t;

}DEP;



STAR E[N_edge];

EDGE edge[N_edge];

DEP xin ,tou;

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

int deep[N_node];

int c1[N_node] ,c2[N_node];

int num[N_edge] ,numt[N_edge];





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;

queue<DEP>q;

q.push(xin);

deep[s] = 0;

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 ++)

listt[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 = listt[s] ;k ;k = E[k].next)

{

listt[s] = k;

int c = E[k].cost ,to = E[k].to;

if(!c || deep[to] != deep[s] + 1)

continue;

int tmp = DFS_Flow(to ,t ,minn(c ,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;

}



int GetMaxFlow(int mid ,int n ,int m)

{

memset(list ,0 ,sizeof(list));

tot = 1;

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

{

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

add(i ,i + n ,INF);

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

}



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

{

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

{

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

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

}

}

return DINIC(0 ,n + n + 1 ,n + n + 1);

}



int main ()

{

int n ,m ,i ,s1 ,s2;

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

{

s1 = s2 = 0;

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

{

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

s1 += c1[i];

}

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

{

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

s2 += c2[i];

}

scanf("%d" ,&m);

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

{

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

numt[i] = edge[i].c;

}



if(s2 < s1)

{

printf("No Solution\n");

continue;

}



sort(numt + 1 ,numt + m + 1);

int numid = 0;

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

if(i == 1 || numt[i] != numt[i-1])

num[++numid] = numt[i];

num[0] = 0;

int low = 0 ,up = numid ,mid ,ans = -1;

while(low <= up)

{

mid = (low + up) >> 1;

if(GetMaxFlow(num[mid] ,n ,m) == s1)

{

ans = num[mid];

up = mid - 1;

}

else low = mid + 1;

}

if(ans == -1) printf("No Solution\n");

else printf("%d\n" ,ans);

}

return 0;

}








举报

相关推荐

0 条评论