bzoj 4276: [ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流

来源:互联网 发布:读取json文件中文乱码 编辑:程序博客网 时间:2024/05/17 21:40

题意

有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],…,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢走c[i]元。作为保安,你在每一段长度为1的时间内最多只能制止一个强盗,那么你最多可以挽回多少损失呢?
n<=5000,ai,bi<=5000

分析

每个小偷往线段树对应区间上连边然后费用流就好了。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=30005;const int inf=0x3f3f3f3f;int n,cnt,last[N],dis[N],ans,s,t,pre[N];bool vis[N];struct edge{int from,to,next,c,w;}e[N*100];queue<int> q;int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}void addedge(int u,int v,int c,int w){    e[++cnt].from=u;e[cnt].to=v;e[cnt].c=c;e[cnt].w=w;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].from=v;e[cnt].to=u;e[cnt].c=0;e[cnt].w=-w;e[cnt].next=last[v];last[v]=cnt;}void build(int d,int l,int r){    if (l==r)    {        addedge(d+n,t,1,0);        return;    }    addedge(d+n,d*2+n,inf,0);addedge(d+n,d*2+1+n,inf,0);    int mid=(l+r)/2;    build(d*2,l,mid);build(d*2+1,mid+1,r);}void ins(int d,int l,int r,int x,int y,int z){    if (x>y) return;    if (l==x&&r==y)    {        addedge(z,d+n,1,0);        return;    }    int mid=(l+r)/2;    ins(d*2,l,mid,x,min(y,mid),z);    ins(d*2+1,mid+1,r,max(x,mid+1),y,z);}bool spfa(){    for (int i=0;i<=t;i++) dis[i]=-inf;    dis[s]=0;q.push(s);    while (!q.empty())    {        int u=q.front();q.pop();        for (int i=last[u];i;i=e[i].next)            if (e[i].c&&dis[u]+e[i].w>dis[e[i].to])            {                dis[e[i].to]=dis[u]+e[i].w;                pre[e[i].to]=i;                if (!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);            }        vis[u]=0;    }    if (dis[t]>-inf) return 1;    else return 0;}void mcf(){    ans+=dis[t];    int x=t;    while (x)    {        e[pre[x]].c--;        e[pre[x]^1].c++;        x=e[pre[x]].from;    }}int main(){    n=read();    s=0;t=n+20005+1;cnt=1;    build(1,1,5000);    for (int i=1;i<=n;i++)    {        int l=read(),r=read(),w=read();        addedge(s,i,1,w);        ins(1,1,5000,l,r-1,i);    }    while (spfa()) mcf();    printf("%d",ans);    return 0;}
阅读全文
0 0