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

网络流+二分构图

2014-05-13 20:51 375 查看
在一个三维空间中有n个点,每个点的坐标都是正整数。第i个点上面有fi个花朵,每个点最多能运送li朵花到其他的点上,每次只能把一个点上的花朵送到距离其R的点上。现在求出最小的R,使得所有的花朵都能被移动到第一个点上。(zoj)

二分枚举最大值R。并用最大流判断是否满流。

源点0 , 汇点1

i - i+n 容量为li

0 - > i 容量为 fi

i+n - > 1 容量为inf 。

i + n ->j 容量为inf (dist[i][j] <= R)

const  int  inf = 1000000000 ;
const  int  maxn = 20000 , maxm = 500000 ;
struct Edge{
int v , f ,next ;
Edge(){}
Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}
};
int  sourse , meet ;
int  id ;
Edge e[maxm*2 + 10] ;
int  g[maxn + 10] ;

void  add(int u , int v , int f){
e[++id] = Edge(v , f ,g[u]) ;
g[u] = id ;
e[++id] = Edge(u , 0 , g[v]) ;
g[v] = id ;
}

queue <int> que ;
bool vis[maxn + 10] ;
int  dist[maxn + 10] ;

void bfs(){
memset(dist , 0 , sizeof(dist)) ;
while(! que.empty()) que.pop() ;
que.push(sourse) ;
vis[sourse] = 1 ;
while(! que.empty()){
int u = que.front() ;  que.pop() ;
for(int i = g[u] ; i ; i = e[i].next){
int v = e[i].v ;
if(e[i].f && !vis[v]){
que.push(v) ;
dist[v] = dist[u] + 1 ;
vis[v] = 1 ;
}
}
}
}

int  dfs(int u , int delta){
if(u == meet) return delta ;
int ans = 0 ;
for(int i = g[u] ; i && delta ; i = e[i].next){
int  v = e[i].v ;
if(e[i].f && dist[v] == dist[u] + 1){
int d = dfs(v , min(delta , e[i].f)) ;
e[i].f -= d ;
e[i^1].f += d ;
delta -= d ;
ans += d ;
}
}
return ans ;
}

int  maxflow(){
int ans = 0 ;
while(1){
memset(vis , 0 , sizeof(vis)) ;
bfs() ;
if(! vis[meet]) return ans  ;
ans += dfs(sourse , inf) ;
}
}

void init(){
memset(g , 0 , sizeof(g)) ;
id = 1 ;
}

struct  Point{
int x , y , z , f , l ;
int dist(Point O){
return (x-O.x)*(x-O.x) + (y-O.y)*(y-O.y) + (z-O.z)*(z-O.z)  ;
}
void read(){
scanf("%d%d%d%d%d",&x,&y,&z,&f,&l) ;
}
}p[108] ;
int  n ;
int  dislen[108][108] ;
int  all ;

int  judge(int len){
init()  ;
int i , j  ;
sourse = 0 ;
meet = 1 ;
for(i = 2 ; i <= n ; i++)
add(sourse , i , p[i].f) ;
for(i = 2 ; i <= n ; i++)
add(i , i+n , p[i].l) ;
for(i = 2 ; i <= n ; i++){
for(j = i+1 ; j <= n ; j++){
if(dislen[i][j] <= len){
add(i+n , j , inf) ;
add(j+n , i , inf) ;
}
}
}
for(i = 2 ; i <= n ; i++){
if(dislen[1][i] <= len)
add(i+n , 1 , inf) ;
}
return maxflow() == all ;
}

int  main(){
int i  , j ;
vector<int> lis ;
while(cin>>n){
all = 0 ;
for(i = 1 ; i <= n ; i++){
p[i].read() ;
all += p[i].f ;
}
all -= p[1].f ;
lis.clear() ;
for(i = 1 ; i <= n ; i++){
for(j = i+1 ; j <= n ; j++){
dislen[i][j] = dislen[j][i] = p[i].dist(p[j]) ;
lis.push_back(dislen[i][j]) ;
}
}
sort(lis.begin() , lis.end()) ;
int S = unique(lis.begin() , lis.end()) - lis.begin() ;
int L = 0  , R = S - 1  , M  , ans = -1 ;
while(L <= R){
M = (L + R) >> 1 ;
if(judge(lis[M])){
ans = lis[M] ;
R = M - 1 ;
}
else   L = M + 1 ;
}
if(ans == -1) puts("-1") ;
else   printf("%.7lf\n" , sqrt(0.0 + ans)) ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: