zoukankan      html  css  js  c++  java
  • BZOJ4669抢夺(费用流+二分答案)

    题目描述

    大战将至, 美国决定实行计划经济。美国西部总共有 N 个城市,编号
    为 0 ∼ N − 1,以及 M 条道路,道路是单向的。其中城市 0 是一个大城
    市,里面住着 K 个人,而城市 N − 1 是一个农业城市。现在所有城市 0 的
    居民都需要到城市 N − 1 去领取食物。由于担心体力不支,所以居民都会
    采取开车的形式出行。但道路不是无限宽的,对于一条道路,会有 ci 的限
    制,表示在同一天内,最多只能有 ci 辆车同时在这条道路上行驶。一条道
    路的长度为 1,每辆车的行驶速度也可以假定为 1 每天。城市 N − 1 会在
    每个居民都到达后马上开始发放食物。现在 Reddington 想知道,假如在最
    优安排下,居民最早能在多少天后领到食物。假如没有居民那就不需要发
    放食物,默认为第 0 天。
    题解
    ORZ zyz
    首先答案具有单调性,可以二分。
    然后贪心一波,我们肯定要捡着最短路去走,然后我们增广出了一条路,因为时间时固定的,所以我们能通过的人数已经确定了。
    就是(T-dis+1)*min(l)前面的是第一波人到终点到结束的时间, minl表示路径权值的最小值。
    然后我们就一直重复这个过程,发现这个过程和EK费用流完全一样。
    代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 1e18
    #define N 1009
    #define M 20002
    using namespace std;
    typedef long long ll;
    queue<int>q; 
    int dis[N],head[N],tot=1,pre[N],n,m,k;
    ll fl[N],num;
    bool vis[N];
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct edge{int n,to,l,f;}e[M];
    inline void add(int u,int v,int l,int f){
        e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;e[tot].f=f;
        e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=0;e[tot].f=-f;
    }
    inline bool spfa(int s,int t){
        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;q.push(s);fl[s]=inf;
        while(!q.empty()){
            int u=q.front();q.pop();vis[u]=0;
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(e[i].l&&dis[v]>dis[u]+e[i].f){
                    dis[v]=dis[u]+e[i].f;pre[v]=i;fl[v]=min(fl[u],1ll*e[i].l);
                    if(!vis[v]){vis[v]=1;q.push(v);}
                }
            }
        }
        return dis[t]!=0x3f3f3f3f;
    }
    struct node{
        int u,v,w;
    }a[M];
    inline void calc(int s,int t,ll mid){
        int x=t;
        while(x!=s){
            int i=pre[x];
            e[i].l-=fl[t];e[i^1].l+=fl[t];x=e[i^1].to;
        }
        num+=max(0ll,1ll*(mid-dis[t]+1)*fl[t]);
    }
    inline bool check(ll mid){
        memset(head,0,sizeof(head));tot=1;num=0;
        for(int i=1;i<=m;++i)add(a[i].u,a[i].v,a[i].w,1);    
        while(spfa(0,n-1))calc(0,n-1,mid);
        return num>=k;
    }
    int main(){
        while(scanf("%d%d%d",&n,&m,&k)!=EOF){
            for(int i=1;i<=m;++i){a[i].u=rd();a[i].v=rd();a[i].w=rd();}
            ll l=0,r=1e12,ans=-1;
            while(l<=r){
                ll mid=(l+r)>>1;
                if(check(mid)){
                    ans=mid;r=mid-1;
                }else l=mid+1;
            }
            if(~ans)printf("%d
    ",ans);else printf("No solution
    ");
        }
        return 0;
    }
  • 相关阅读:
    Java实现 蓝桥杯VIP 基础练习 回形取数
    Java实现 蓝桥杯VIP 基础练习 回形取数
    Java实现 蓝桥杯VIP 基础练习 回形取数
    Java实现 蓝桥杯VIP 基础练习 回形取数
    Java实现 蓝桥杯VIP 基础练习 报时助手
    Java实现 蓝桥杯VIP 基础练习 报时助手
    Java实现 蓝桥杯VIP 基础练习 报时助手
    Java实现 蓝桥杯VIP 基础练习 报时助手
    Java实现 蓝桥杯VIP 基础练习 报时助手
    block的是发送信号的线程,又不是处理槽函数的线程
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10225915.html
Copyright © 2011-2022 走看看