【bzoj1520】 [POI2006]Szk-Schools

Description

Input

Output

如果有可行解, 输出最小代价,否则输出NIE.

Sample Input

5
1 1 2 3
1 1 5 1
3 2 5 5
4 1 5 10
3 3 3 1

Sample Output

9


最小费用最大流,满流即有合法解

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#define st (2*n+1)
#define en (2*n+2)
using namespace std;
int fi[405],ne[200000],j[200000],k[200000],c[200000],step=1;
int n,l,r,co,m,ans,minn,sum;
int que[200000],tot,tow,dis[405],bian[405],fa[405];
bool flag[405];
inline void addedge(int fr,int to,int flow,int cost){
    j[++step]=to;k[step]=flow;c[step]=cost;
    ne[step]=fi[fr];fi[fr]=step;
     
    j[++step]=fr;k[step]=0;c[step]=-cost;
    ne[step]=fi[to];fi[to]=step;
}
inline bool spfa(){
    memset(dis,60,sizeof(dis));
    que[tot=tow=1]=st;dis[st]=0;
    while (tot<=tow){
        flag[que[tot]]=0;
        for (int u=fi[que[tot]];u;u=ne[u])
            if (dis[j[u]]>dis[que[tot]]+c[u] && k[u]>0){
                dis[j[u]]=dis[que[tot]]+c[u];
                bian[j[u]]=u;
                fa[j[u]]=que[tot];
                if (!flag[j[u]]){
                    flag[j[u]]=1;
                    que[++tow]=j[u];
                }
            }
        ++tot;
    }
    if (dis[en]==dis[0])return false;
    minn=1e9;
    for (int i=en;i!=st;i=fa[i])
        minn=min(minn,k[bian[i]]);
    sum+=minn;
    for (int i=en;i!=st;i=fa[i]){
        k[bian[i]]-=minn;
        k[bian[i]^1]+=minn;
        ans+=c[bian[i]];
    }
    return true;
}
int main (){
    scanf ("%d",&n);
    for (int i=1;i<=n;++i){
        scanf ("%d%d%d%d",&m,&l,&r,&co);
        addedge(st,i,1,0);
        addedge(n+i,en,1,0);
        for (int q=l;q<=r;++q)
            addedge(i,n+q,1,abs(q-m)*co);
    }
    while (spfa());
    if (sum==n)printf ("%d",ans);
    else puts("NIE");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值