Bajtman i Okrągły Robin

Bajtman i Okrągły Robin

题目描述

 

你是一个保安,你发现有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间进行抢劫,并计划抢走c[i]元。你在一个强盗任何一个作案的时间阻止他,你就可以挽回这个强盗带来的损失。显然,对于每个强盗,你只能挽回一次损失。不幸的是,你在每一段长度为1的时间内最多只能制止一个强盗,那么你最多可以挽回多少损失呢?

 

输入

第一行包含一个正整数n(1<=n<=5000),表示强盗的个数。
接下来n行,每行包含三个正整数a[i],b[i],c[i](1<=a[i]<b[i]<=5000,1<=c[i]<=10000),依次描述每一个强盗。

输出

输出一个整数,即可以挽回的损失的最大值。

 

 

样例输入

4
1 4 40
2 4 10
2 3 30
1 3 20

样例输出

90

提示

注意题面中的时间段跟时间点是不一样的。

 

solution

考虑网络流

把时间段建成点,强盗也建成点,源点向时间段连边(1,0),强盗向汇点连边(1,0),时间段向强盗连边(1,-C[i]),

然后费用流即可。

然而边最多有5000*5000条,会T。

用线段树优化网络流建图:把时间段开成线段树每个,强盗连对应的节点。

子节点向父节点连边,S向叶子连边

由于一段区间对应线段树上不超过logn段区间,所以边数不超过nlogn

然后就可以了

吐槽数据,一直T

居然卡zkw

优化:

1.线段树不建满

2.把边反着建

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 30005
#define inf 1e9
using namespace std;
int n,co,S,T,tot=1,head[maxn],li,ri,cost;
int d[maxn],flag[maxn],ans,cur[maxn],pre[maxn];
queue<int>q;
struct node{
    int id,v,nex,cap,w;
}e[200002];
struct no{
    int l,r;
}tree[maxn*4];
int ll[5022],rr[5022],c[5022];
void lj(int t1,int t2,int t3,int t4){
    tot++;e[tot].id=t1;e[tot].v=t2;e[tot].cap=t3;e[tot].w=t4;e[tot].nex=head[t1];head[t1]=tot;
}
void build(int k,int L,int R){
    tree[k].l=L,tree[k].r=R;
    if(L==R){
        lj(S,k,1,0);lj(k,S,0,0);
        co=max(co,k);
        return;
    }
    int mid=L+R>>1;
    build(k*2,L,mid);build(k*2+1,mid+1,R);
    lj(k*2,k,mid-L+1,0);lj(k,k*2,0,0);
    lj(k*2+1,k,R-mid,0);lj(k,k*2+1,0,0);
}
void jia(int k,int pl){
    if(tree[k].l>=li&&tree[k].r<=ri){
        lj(k,pl,1,-cost);lj(pl,k,0,cost);
        return;}
    int mid=tree[k].l+tree[k].r>>1;
    if(li<=mid)jia(k*2,pl);
    if(ri>mid)jia(k*2+1,pl);
}
bool SPFA()
{
    for(int i=1;i<=T;i++)flag[i]=0,d[i]=inf;
    d[S]=0;flag[S]=1;q.push(S);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=head[x];i;i=e[i].nex){
               
            if(e[i].cap>0&&d[e[i].v]>d[x]+e[i].w){
                d[e[i].v]=d[x]+e[i].w;pre[e[i].v]=i;
                if(!flag[e[i].v])
                {
                    flag[e[i].v]=1;q.push(e[i].v);  
                }
            }   
        }
        flag[x]=0;  
    }
    if(d[T]==inf)return 0;
    int u=pre[T],mi=inf;
    while(1)
    {
        mi=min(e[u].cap,mi);
        if(e[u].id==S)break;
        u=pre[e[u].id];
    }
    u=pre[T];
    while(1)
    {
        e[u].cap-=mi;e[u^1].cap+=mi;
        if(e[u].id==S)break;
        u=pre[e[u].id]; 
    }
    ans+=d[T]*mi;
    return 1;
}
int main(){
    cin>>n;
    S=30000,T=30001;
    int Max=0;
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&ll[i],&rr[i],&c[i]);
        rr[i]--;Max=max(Max,rr[i]);
    }
    build(1,1,Max);
    for(int i=1;i<=n;i++){
        li=ll[i];ri=rr[i];cost=c[i];
        jia(1,co+i);
        lj(co+i,T,1,0);lj(T,co+i,0,0);
    }
    while(SPFA());
    cout<<-ans<<endl;
    return 0;
}

 

 

 

posted @ 2018-08-10 09:22  liankewei123456  阅读(178)  评论(0编辑  收藏  举报