Gym - 101492I 区间限制费用流

 

https://cn.vjudge.net/problem/Gym-101492I

如果用单个点代表每个区间 利用拆点来限制区间的流量的话 点是 n^2/2+m个 边是2*n^2条

但是这样会T

解法1:单纯形

单纯形套板可以过

#include <bits/stdc++.h>
#define N
using namespace std;

typedef unsigned ui;
typedef long double dbl;

const dbl eps = 1e-8;

ui n, m, c[5001]; dbl a[4001][201], x[201], z;

int dcmp(dbl d) { return d < -eps ? -1 : d <= eps ? 0 : 1; }

//    u in, v out
void pivot(ui u, ui v) {
    swap(c[n + u], c[v]);
    //    row u *= 1 / a[u][v]
    dbl k = a[u][v]; a[u][v] = 1;
    for (ui j = 0; j <= n; ++j) a[u][j] /= k;
    for (ui i = 0; i <= m; ++i) {
        if (i == u || !dcmp(a[i][v])) continue;
        k = a[i][v]; a[i][v] = 0;
        for (ui j = 0; j <= n; ++j)
            a[i][j] -= a[u][j] * k;
    }
}

bool init() {
    for (ui i = 1; i <= n; ++i) c[i] = i;
    while (1) {
        ui u = 0, v = 0;
        for (ui i = 1; i <= m; ++i)
            if (dcmp(a[i][0]) == -1 && (!u || dcmp(a[u][0] - a[i][0]) == 1)) u = i;
        if (!u) return 1;
        for (ui j = 1; j <= n && !v; ++j)
            if (dcmp(a[u][j]) == -1) v = j;
        if (!v) return 0;
        pivot(u, v);
    }
}

int simplex() {
    if (!init()) return 0;
    else while (1) {
        ui u = 0, v = 0;
        for (ui j = 1; j <= n; ++j)
            if (dcmp(a[0][j]) == 1 && (!v || a[0][j] > a[0][v])) v = j;

        if (!v) {
            z = -a[0][0];
            for (ui i = 1; i <= m; ++i)
                x[c[n + i]] = a[i][0];
            return 1;
        }

        dbl w = 1e20;
        for (ui i = 1; i <= m; ++i)
            if (dcmp(a[i][v]) == 1 &&
                dcmp(w - a[i][0] / a[i][v]) == 1) {
                w = a[i][0] / a[i][v];
                u = i;
            }
        if (!u) return 2;
        pivot(u, v);
    }
}


int main(void) {
    ios::sync_with_stdio(0); cin.tie(0);
#ifndef ONLINE_JUDGE
    ifstream cin("1.in");
#endif
    ui t;
    cin >> n >> m;
    for (ui j = 1; j <= n; ++j) cin >> a[0][j];
    for (ui i = 1; i <= m; ++i) {
        int l, r; cin >> l >> r;
        for (int j = l; j <= r; ++j)
            a[i][j] = 1;
        cin >> a[i][0];
    }

    int res = simplex();
    if (res == 0) cout << "Infeasible" << endl;
    else if (res == 2) cout << "Unbounded" << endl;
    else {
        cout << (long long)z << endl;
    }
    return 0;
}
View Code

解法2:网络流

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<string.h>
#include<string>
#include<stdlib.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn=300;
const int maxm=10005;
struct node
{
    int t,f,c,next;
}e[maxm*2];
int a[maxn];
int head[maxn],dis[maxn],vis[maxn];
int pre[maxn];
int cnt,s,t;
void add(int s,int t,int c,int f)
{
    e[cnt].t=t;
    e[cnt].c=c;
    e[cnt].f=f;
    e[cnt].next=head[s];
    head[s]=cnt++;
    e[cnt].t=s;
    e[cnt].c=0;
    e[cnt].f=-f;
    e[cnt].next=head[t];
    head[t]=cnt++;
}
void intt()
{
    cnt=0;
    s=0;t=250;
    memset(head,-1,sizeof(head));
}
int spfa()
{
    queue<int >que;
    for(int i=0;i<maxn;i++)
    {
        dis[i]=inf;
        vis[i]=0;
        pre[i]=-1;
    }
    dis[s]=0;
    vis[s]=1;
    que.push(s);
    while(que.size())
    {
        int u=que.front();
        que.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].t;
            if(e[i].c>0&&dis[u]+e[i].f<dis[v])
            {
                dis[v]=dis[u]+e[i].f;
                pre[v]=i;
                if(vis[v]==0)
                {
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
    if(pre[t]==-1)return 0;
    return 1;
}
ll mincost()
{
    int flow=0;
    ll cost=0;
    while(spfa())
    {
      int tf=inf;
      for(int i=pre[t];i!=-1;i=pre[e[i^1].t])
            tf=min(e[i].c,tf);
      flow+=tf;
      for(int i=pre[t];i!=-1;i=pre[e[i^1].t])
      {
          e[i].c-=tf;
          e[i^1].c+=tf;
          cost+=1ll*e[i].f*tf;
      }
    }
    return cost;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    intt();
    for(int i=1;i<=m;i++)
    {
        int u,v,k;
        scanf("%d%d%d",&u,&v,&k);
        add(u,v+1,inf,k);
    }
    for(int i=n+1;i>=2;i--)
        add(i,i-1,inf,0);
    for(int i=n+1;i>=1;i--)
        {
            int temp=a[i]-a[i-1];
            if(temp<0)
            {
                add(i,t,-temp,0);
            }
            else add(s,i,temp,0);
        }
    printf("%lld\n",mincost());
}
View Code

转载自https://blog.csdn.net/dhydye/article/details/80515359 不懂原理QAQ

posted @ 2019-07-15 20:28  Aragaki  阅读(148)  评论(0编辑  收藏  举报