1. 程式人生 > >zoj 3691 二分+最大流

zoj 3691 二分+最大流

傳送門

其他不講,就說說建圖吧,下面以3個點為例:


我用的演算法效率不高,想更快的可以用dinic或sap

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,en;
int f[41111];
int fst[333],next[41111],node[41111],c[41111],lu[333],pre[333];
double l[41111];
double x[333],y[333],z[333];
int jj[333],cc[333];
bool vis[333];
int q[33333];
int af;
void init()
{
    af=0;
    en=0;
    memset(fst,-1,sizeof(fst));
}
void add(int u,int v,double d,int cnt)
{
    //cout<<u<<" "<<v<<" "<<d<<" "<<cnt<<endl;
    next[en]=fst[u];
    fst[u]=en;
    node[en]=v;
    l[en]=d;
    c[en]=cnt;
    en++;
}
double dis(int i,int j)
{
    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]));
}
void build()
{
    for(int i=1; i<=n; i++)
    {
        add(0,i,0,jj[i]);
        add(i,0,0,0);
    }
    for(int i=2; i<=n; i++)
    {
        for(int j=2; j<=n; j++)
        {
            double d=dis(i,j);
            if(i==j)
            {
                add(i,n+j,d,cc[i]);
                add(n+j,i,d,0);
            }
            else
            {
                add(n+j,i,d,cc[j]);
                add(i,n+j,d,0);
            }
        }
    }
    for(int i=2; i<=n; i++)
    {
        double d=dis(1,i);
        add(n+i,1,d,cc[i]);
        add(1,n+i,d,0);
    }
}
bool bfs(int s,int t,double d)
{
    memset(vis,0,sizeof(vis));
    int fn=0,ed=0;
    q[ed++]=0;
    vis[0]=1;
    while(fn<ed)
    {
        int u=q[fn++];
        for(int i=fst[u]; i!=-1; i=next[i])
        {
            if(d-l[i]<1e-9)continue;
            int v=node[i];
            if(c[i]-f[i]>0&&!vis[v])
            {
                pre[v]=u;
                lu[v]=i;
                if(v==t)return true;
                q[ed++]=v;
                vis[v]=1;
            }
        }
    }
    return false;
}
int ek(int s,int t,double d)
{
    int ans=0;
    memset(f,0,sizeof(f));
    while(bfs(s,t,d))
    {
        int mm=af;
        for(int i=t; i!=s; i=pre[i])
        {
            int v=lu[i];
            if(mm>c[v]-f[v])mm=c[v]-f[v];
        }
        for(int i=t; i!=s; i=pre[i])
        {
            int v=lu[i];
            f[v]+=mm;
            f[v^1]-=mm;
        }
        ans+=mm;
    }
    return ans;
}
void solve()
{
    double low=0,high=40000,mid;
    while(high-low>1e-9)
    {
        mid=(high+low)/2.0;
        if(ek(0,1,mid)==af)high=mid;
        else low=mid;
    }
    if(low>39999)cout<<-1<<endl;
    else printf("%.7f\n",low);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init();
        bool fff=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%lf%lf%lf%d%d",&x[i],&y[i],&z[i],&jj[i],&cc[i]);
            af+=jj[i];
            if(jj[i]>cc[i]&&i!=1)fff=1;
        }
        if(fff)
        {
            cout<<-1<<endl;
            continue;
        }
        build();
        solve();
    }
    return 0;
}


相關推薦

zoj 3691 二分+

傳送門 其他不講,就說說建圖吧,下面以3個點為例: 我用的演算法效率不高,想更快的可以用dinic或sap #include<iostream> #include<cstdio> #include<cstring> #include&

uvalive 3231 Fair Share 公平分配問題 二分+ 右邊多流量的結點流量盡量少。

init targe memset save amp class tps blog ext /** 題目: uvalive 3231 Fair Share 公平分配問題 鏈接:https://vjudge.net/problem/UVALive-3231 題意:有m個任務

HDU4560 二分

  http://acm.hdu.edu.cn/showproblem.php?pid=4560 網路流好像經常搭配上二分和拆點。   n個歌手,m種歌曲流派(n<=m<=75) 我們想要安排儘可能多的演唱會。不過有以下條件—— 1,每場演唱會中,每個歌手要唱

G - Gasoline Gym - 101908G[二分]

題意:給出R個提供點,P個接收點,每個接收點都要接收滿,還有一個運輸的時間,問最小時間能夠完成所有的運輸。 題解:首先很容易想到費用流,當然T了 O

bzoj 1189 二分+

const noi2007 truct span find() for 問題 思路 check 題目傳送門 思路:   先預處理出每個人到每扇門的時間,用門作為起點進行bfs處理。   然後二分時間,假設時間為x,將每扇門拆成1到x,x個時間點,表示這扇門有幾個時間點是可以

bzoj 1189 二分+

題目傳送門 思路:   先預處理出每個人到每扇門的時間,用門作為起點進行bfs處理。   然後二分時間,假設時間為x,將每扇門拆成1到x,x個時間點,表示這扇門有幾個時間點是可以出去的。對於一扇門,每個時間點都向後一個時間點建邊,表示人在當前時間點到達,可以在下一時間點出去。   先將s連上所有的空地

UVA 1345 Jamie's Contact Groups(二分+

題意:有n個人,m個組,給出每個人想要去的分組,每個人只能去一個組,問人數最多的那個組最少有多少個人 二分一下每個組的可以放的人數,然後每個組與匯點相連,容量為二分的值,源點與每個人相連,容量為1,每個人與想去的組連邊,容量為1,跑一邊最大流判斷即可 #include

HDU 3081 並查集+二分+

AC程式碼 #include<bits/stdc++.h> using namespace std; #define maxn 500 #define maxm 10000000 #define inf 0x3f3f3f3f int first[max

poj2455 二分裸題

一道二分最大流的裸題 問你john要從1號去n號點T次(到了n號點直接瞬間移動回1號點,就是直接把他放回1號點,且之前走的邊不能再走了),問在這T次中走的最長的一條邊最小是多少(注意:不是從1號到n號的總距離的最大值 而是某條邊的最大值) 二分距離 如果某條邊的流量<

loj 1167(二分+

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include&l

poj 2391(二分+)

思路:求最短時間,可以想到二分,然後判斷可行性。首先在原圖上求 floyd,得到每兩個棚之間的最短距離。然後拆點:將每個棚拆為 i 和 i’(流進和流出),添邊(i,i’,INF)。增加源點 s 和匯點 t,從 s 連邊到 i,容量為該棚現在的貓的數量,i’連邊到 t,容量

poj 2112(二分+)

Optimal Milking Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 6483 Accepted: 2428 Case Time Limit: 1000MS Description

poj 2455(二分+)

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using name

POJ 2455 二分

Secret Milking Machine Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8660 Accepted: 2599 Description Farmer John is cons

poj2112 二分+

* Line 1: A single line with three space-separated integers: K, C, and M.  * Lines 2.. ...: Each of these K+C lines of K+C space-separated integers descri

BZOJ3993 星際戰爭 題解(二分+)

星際戰爭 【問題描述】 3333年,在銀河系的某星球上,X軍團和Y軍團正在激烈地作戰。在戰鬥的某一階段,Y軍團一共派遣了N個巨型機器人進攻X軍團的陣地,其中第i個巨型機器人的裝甲值為Ai。當一個巨型機器人的裝甲值減少到0或者以下時,這個巨型機器人就被摧毀了。X軍團有M個鐳射

poj2391Floyd+二分+

好吧算增加了一個模板吧。。 過兩天要校賽了,沒過的題先放著,這兩天把做過的整理整理。 構圖思路:將點拆分成2組,一組代表牛,一組代表遮蔽點,然後構建源點和匯點; 用floyd求出點與點之間的最大距離,根據最大距離開始二分,使距離小於mid的點在最大流中開路,若得出最大流等於

poj2112 二分+Floyd

題意:      一個農場主有一些奶牛,和一些機器,每臺機器有自己的服務上限,就是一天最多能給多少頭奶牛擠奶,給你任意兩點的距離,問你讓所有的奶牛都被擠奶時,奶牛於機器最遠距離的最近是多少。 思路:       求最遠的最近,二分,然後用最大流去判斷是否所有的奶牛都被擠奶了

POJ2584_T-Shirt Gumbo(二分圖多重匹配/)

make sdn iss ... spa scanf ams ipp char s 解題報告 http://blog.csdn.net/juncoder/article/details/38239367 題目傳送門 題意: X個參賽選手,每一個選手有衣服

Risk UVA - 12264 拆點法++二分

sizeof main net style ati continue ons class tps /** 題目:Risk UVA - 12264 鏈接:https://vjudge.net/problem/UVA-12264 題意:給n個點的無權無向圖(n<=100