• [2020杭电多校第二场]1005 New Equipments(费用流)


    首先,明显的网络流。那么如何建边,对于每个二次函数在[1,m]里挑n个函数值最小的点, 这样子一共n^2个点,注意还要去重。这n^2个点其实就能使得n个二次函数(a, b, c)完全匹配。

    那么流量全部设为1,费用是对应的函数值。超级源点和终点费用为0;但是,跑n次费用流时间不允许,但是你仔细想每次增广只会多1的流量,那么其实只要跑一次就行。每次增广完输出当前的费用即可,

    //#pragma GCC optimize("-Ofast","-funroll-all-loops")
    //freopen("C://std/a.in","r",stdin);
    //freopen("C://std/b.txt","w",stdout);
    #include<bits/stdc++.h>
    #define ll long long
    #define PB push_back
    #define endl '
    '
    #define INF 0x3f3f3f3f
    #define LINF 0x3f3f3f3f3f3f3f3f
    #define ull unsigned long long
    #define lson rt << 1, l, mid
    #define rson rt << 1 | 1, mid + 1, r
    #define lowbit(x) (x & (-x))
    #define rep(i, a, b) for(int i = a ; i <= b ; ++ i)
    #define per(i, a, b) for(int i = b ; i >= a ; -- i)
    #define clr(a, b) memset(a, b, sizeof(a))
    #define in insert
    #define random(x) (rand()%x)
    #define PII(x, y) make_pair(x, y)
    #define fi first
    #define se second
    #define pi acos(-1)
    #define re register
    //std::ios::sync_with_stdio(false);
    #define int long long
    using namespace std;
    const int maxn = 2e4 + 50;
    const int inf = 0x3f3f3f3f3f3f3f3f;
    const int N = 5010, M = 2e5+10;
    int n,m,s,T,t,v[N],e[N];
    int head[N],nex[M],to[M],flow[M],tot=1;
    int a[N],b[N],c[N],p[N][N],h[N],d[N],w[M],res,maxflow;
    inline void ade(int a,int b,int c,int d){
        to[++tot]=b; nex[tot]=head[a]; w[tot]=d; flow[tot]=c; head[a]=tot;
    }
    inline void add(int a,int b,int c,int d){ade(a,b,c,d);    ade(b,a,0,-d);}
    inline ll dijkstra(){
        memset(d,inf,sizeof d);    d[s]=0;    int vis[N]={0};
        priority_queue<pair<int,int> > q;    q.push({0,s});
        while(q.size()){
            int u=q.top().second;    q.pop();
            if(vis[u])    continue;    vis[u]=1;
            for(int i=head[u];i;i=nex[i]){
                if(flow[i]&&d[to[i]]>d[u]+w[i]+h[u]-h[to[i]]){
                    d[to[i]]=d[u]+w[i]+h[u]-h[to[i]];
                    v[to[i]]=u; e[to[i]]=i;    q.push({-d[to[i]],to[i]});
                }
            }
        }
        for(int i=1;i<=t;i++)    if(d[i]<inf)    h[i]+=d[i];
        return d[t]<inf;
    }
    void EK(){
        while(dijkstra()){
            int mi=inf;
            for(int i=t;i!=s;i=v[i])    mi=min(mi,1LL*flow[e[i]]);
            for(int i=t;i!=s;i=v[i])    flow[e[i]]-=mi,flow[e[i]^1]+=mi;
            res+=h[t]*mi,maxflow+=mi;
            cout << res;
            if(maxflow != n) cout << ' ';
        }
        puts("");
    }
    ll f(ll i, ll j){
        return j * j * a[i] + j * b[i] + c[i];
    }
    signed main(){
        scanf("%lld", &T);
        while(T --){
            scanf("%lld %lld", &n, &m);
            vector<int> sm;
            res = maxflow = 0; tot = 1;
            clr(head, 0);
            clr(h, 0);
            rep(i, 1, n){
                scanf("%lld %lld %lld", &a[i], &b[i], &c[i]);
                int mid = 0, k = 1;
                if(b[i] >= 0) mid = 1;
                else{
                    int l = floor(-0.5 * b[i] / a[i]);
                    int r = ceil(-0.5 * b[i] / a[i]);
                    if(l >= 1 && l <= m){
                        if(f(i, l) < f(i, r)) mid = l;
                        else mid = r;
                    }
                    else mid = r;
                }
                p[i][k] = mid; sm.PB(mid);
                int l = mid - 1, r = mid + 1;
                while(k < n){
                    if(f(i, l) < f(i, r)){
                        if(l >= 1 && l <= m) p[i][++k] = l --;
                        else if(r >= 1 && r <= m) p[i][++k] = r ++;
                    }
                    else{
                        if(r >= 1 && r <= m) p[i][++k] = r ++;
                        else if(l >= 1 && l <= m) p[i][++k] = l --;
                    }
                    sm.PB(p[i][k]);
                }
            }
            sort(sm.begin(), sm.end());
            sm.erase(unique(sm.begin(), sm.end()), sm.end());
            m = (int)sm.size(); s = n + m + 1; t = s + 1;
            rep(i, 1, n){
                add(s, i, 1, 0);
                rep(j, 1, n){
                    int v = lower_bound(sm.begin(), sm.end(), p[i][j]) - sm.begin() + 1;
                    add(i, v + n, 1, f(i, p[i][j]));
                }
            }
            rep(i, 1, m) add(i + n, t, 1, 0);
            EK();
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Geohash
    Go加密解密之RSA[转]
    在MACOS上实现交叉编译
    [转]MySQL与MongoDB的操作对比
    CentOS 6 使用 yum 安装MongoDB及服务器端配置
    Ubuntu下PHP的扩展
    golang 图片处理,剪切,base64数据转换,文件存储
    性能测试应用领域
    性能测试用例、策略和方法
    性能测试类型
  • 原文地址:https://www.cnblogs.com/Ketchum/p/13384723.html
Copyright © 2020-2023  润新知