zoukankan      html  css  js  c++  java
  • Poj 2391 二分答案+最大流+拆点

    时限卡的非常紧,做尽常数优化才过。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <climits>
    #include <string>
    #include <iostream>
    #include <map>
    #include <cstdlib>
    #include <list>
    #include <set>
    #include <queue>
    #include <stack>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    const int maxn = 505;
    const int maxm = maxn * maxn;
    const LL INF = 1e14;
    struct Edge {
        int u,v; LL w;
        bool operator < (const Edge &x) const {
            return w < x.w;
        }
    };
    LL dist[maxn][maxn],cow_cnt[maxn],sj_cnt[maxn],cow_sum;
    LL cap[maxm],v[maxm],maxedge;
    Edge e[maxm];
    int first[maxn],nxt[maxm];
    int n,m,s,t,ecnt,oecnt;
    
    void adde(int uu,int vv,LL ww) {
        v[ecnt] = vv; cap[ecnt] = ww; nxt[ecnt] = first[uu]; first[uu] = ecnt++;
        v[ecnt] = uu; cap[ecnt] = 0; nxt[ecnt] = first[vv]; first[vv] = ecnt++;
    }
    
    void floyd() {
        maxedge = -1;
        for(int k = 1;k <= n;k++) {
            for(int i = 1;i <= n;i++) {
                for(int j = 1;j <= n;j++) {
                    dist[i][j] = min(dist[i][k] + dist[k][j],dist[i][j]);
                }
            }
        }
        oecnt = 0;
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= n;j++) {
                if(dist[i][j] != INF) {
                    maxedge = max(maxedge,dist[i][j]);
                    e[oecnt].u = i; e[oecnt].v = j; e[oecnt].w = dist[i][j]; oecnt++;
                }
            }
            e[oecnt].u = i; e[oecnt].v = i; e[oecnt].w = 0; oecnt++;
        }
        sort(e,e + oecnt);
    }
    
    void input() {
        memset(first,-1,sizeof(first));
        memset(nxt,-1,sizeof(nxt));
        s = 0; t = (n << 1) | 1;
        cow_sum = 0;
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= n;j++) {
                dist[i][j] = INF;
            }
        }
        for(int i = 1;i <= n;i++) {
            scanf("%lld%lld",&cow_cnt[i],&sj_cnt[i]);
            cow_sum += cow_cnt[i];
        }
        for(int i = 1;i <= m;i++) {
            int u,v; LL w;
            scanf("%d%d%lld",&u,&v,&w);
            dist[u][v] = dist[v][u] = min(dist[u][v],w);
        }
        floyd();
    }
    
    void build_graph(LL minval) {
        memset(first,-1,sizeof(first));
        ecnt = 0;
        for(int i = 1;i <= n;i++) {
            adde(i + n,t,sj_cnt[i]);
            adde(s,i,cow_cnt[i]);
        }
        for(int i = 0;i < oecnt;i++) {
            if(e[i].w > minval) break;
            adde(e[i].u,e[i].v + n,INF);
        }
    }
    
    int q[maxn * 2],qs,qe,level[maxn];
    bool bfs() {
        memset(level,0,sizeof(level));
        qs = 0; qe = 1;
        q[qs] = s; level[s] = 1;
        while(qs < qe) {
            int now = q[qs++];
            for(int i = first[now];i != -1;i = nxt[i]) {
                if(level[v[i]] == 0 && cap[i] != 0) {
                    q[qe++] = v[i]; level[v[i]] = level[now] + 1;
                }
            }
        }
        return level[t];
    }
    
    LL dinic(int now,LL alpha) {
        if(now == t) return alpha;
        LL sum = 0;
        for(int i = first[now];i != -1 && sum < alpha;i = nxt[i]) {
            if(cap[i] && level[v[i]] == level[now] + 1) {
                LL ret = dinic(v[i],min(alpha,cap[i]));
                alpha -= ret; sum += ret;
                cap[i] -= ret; cap[i ^ 1] += ret;
            }
        }
        if(sum == 0) level[now] = -1;
        return sum;
    }
    
    bool ok(LL val) {
        LL ans = 0;
        build_graph(val);
        while(bfs()) ans += dinic(s,INF);
        return ans >= cow_sum;
    }
    
    void solve() {
        LL l = 1,r = maxedge,ans = -1,mid;
        while(l <= r) {
            mid = (l + r) >> 1;
            if(ok(mid)) {
                r = mid - 1; ans = mid;
            } else l = mid + 1;
        }
        printf("%lld
    ",ans);
    }
    
    int main() {
        while(~scanf("%d%d",&n,&m)) {
            input();
            solve();
        }
        return 0;
    }
    

      

  • 相关阅读:
    搭建UEFI PXE 基于linux相关资料
    SLES 搭建dhcp6服务器
    SUSE Linux 11架设Apache虚拟主机
    Virtualbox 安装SLES11 SP4系统后安装Guest Additions
    centos7 安装wireshark
    RHEL7.x 安装virtualbox增强组件
    Readhat 7.x禁用防火墙
    Debian普通用户添加sudo权限
    Virtualbox 错误提示"VT-x is not available (VERR_VMX_NO_VMX)"解决办法
    VNC 下载地址和key
  • 原文地址:https://www.cnblogs.com/rolight/p/3871081.html
Copyright © 2011-2022 走看看