4276: [ONTAK2015]Bajtman i Okrągły Robin
4276: [ONTAK2015]Bajtman i Okrągły Robin
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 345 Solved: 186
[Submit][Status][Discuss]
Description
有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢走c[i]元。作为保安,你在每一段长度为1的时间内最多只能制止一个强盗,那么你最多可以挽回多少损失呢?
Input
第一行包含一个正整数n(1<=n<=5000),表示强盗的个数。
接下来n行,每行包含三个正整数a[i],b[i],c[i](1<=a[i]<b[i]<=5000,1<=c[i]<=10000),依次描述每一个强盗。
Output
输出一个整数,即可以挽回的损失的最大值。
Sample Input
4
1 4 40
2 4 10
2 3 30
1 3 20
1 4 40
2 4 10
2 3 30
1 3 20
Sample Output
90
HINT
Source
民间解法:
//(贪心)按权值排序匈牙利 /************************************************************** Problem: 4276 User: gryz2016 Language: C++ Result: Accepted Time:16732 ms Memory:948 kb ****************************************************************/ #include<cstdio> #include<algorithm> using namespace std; inline 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; } const int N=5005; struct node{int a,b,w;}f[N]; int n,ans,person,match[N],times[N]; inline bool cmp(const node &a,const node &b){ return a.w>b.w; } bool hunguary(int x){ times[x]=person; for(int i=f[x].a;i<=f[x].b;i++){ if(!match[i]||(times[match[i]]!=person&&hunguary(match[i]))){ match[i]=x; return 1; } } return 0; } int main(){ n=read(); for(int i=1;i<=n;i++) f[i].a=read(),f[i].b=read()-1,f[i].w=read(); sort(f+1,f+n+1,cmp); for(int i=1;i<=n;i++){ person++; if(hunguary(i)) ans+=f[i].w; } printf("%d",ans); return 0; }
官方解法:
费用流作法是最暴力最显然的吧。。
一眼建图题,跑最大费用流,所以裸的是水不过去的。。
朴素建图:用xi表示每个强盗,用yi表示区间[i,i+1]。
(S,xi,1,ci)
(xi,yi(ai<=yi<bi),1,0)
(yi,T,1,0)
然后这样是过不了的。
我们发现每次连边都是左边一个点对应右边一段连续的区间,所以可以用线段树来优化。
在原来的基础上,我们不再从xi向每个对应的yi连边,而用线段树中的点来表示区间[ai,bi),然后连边。
对于线段树中的点,由父亲向儿子连容量为inf,费用为0的边。
由叶子节点向汇点T连容量为1,费用为0的边。
然后跑费用流。(引自ws_fqk)
/************************************************************** Problem: 4276 User: gryz2016 Language: C++ Result: Accepted Time:31629 ms Memory:5736 kb ****************************************************************/ #include<cstdio> #include<iostream> #define lc k<<1 #define rc k<<1|1 using namespace std; inline 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; } const int N=30005; const int M=2e5+5; const int inf=~0u>>2; struct node{int v,cap,cost,next;}e[M];int tot=1,head[N]; int n,ans,S,T,num,dis[N],id[N],li[N],ri[N],ls[N],rs[N],prev[N],flow[N],q[N*2]; bool vis[N]; void add(int x,int y,int z,int cost){ e[++tot].v=y;e[tot].cap=z;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].cap=0;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot; } void build(int k,int l,int r){ id[k]=++num; if((li[k]=l)==(ri[k]=r)){ add(id[k],T,1,0); return ; } int mid=l+r>>1; build(ls[k]=lc,l,mid); build(rs[k]=rc,mid+1,r); add(id[k],id[ls[k]],inf,0); add(id[k],id[rs[k]],inf,0); } void insert(int k,int opl,int opr,int now){ if(li[k]==opl&&ri[k]==opr){ add(now,id[k],1,0); return ; } int mid=li[k]+ri[k]>>1; if(opr<=mid) insert(ls[k],opl,opr,now); else if(opl>mid) insert(rs[k],opl,opr,now); else insert(ls[k],opl,mid,now),insert(rs[k],mid+1,opr,now); } bool spfa(){ for(int i=S;i<=T;i++) vis[i]=0,dis[i]=-1; int h=0,t=1;q[t]=S;dis[S]=0;flow[S]=inf; while(h!=t){ int x=q[++h];vis[x]=0; for(int i=head[x];i;i=e[i].next){ if(e[i].cap&&dis[e[i].v]<dis[x]+e[i].cost){ dis[e[i].v]=dis[x]+e[i].cost; prev[e[i].v]=i; flow[e[i].v]=min(flow[x],e[i].cap); if(!vis[e[i].v]){ vis[e[i].v]=1; if(dis[e[i].v]>dis[x]) q[h--]=e[i].v; else q[++t]=e[i].v; } } } } return dis[T]!=-1; } void augment(){ for(int i=T;i!=S;i=e[prev[i]^1].v){ e[prev[i]].cap-=flow[T]; e[prev[i]^1].cap+=flow[T]; } ans+=dis[T]*flow[T]; } int main(){ n=read();S=0;T=30000; build(1,1,5000); for(int i=1,a,b,c;i<=n;i++){ a=read();b=read()-1;c=read(); add(S,++num,1,c); insert(1,a,b,num); } while(spfa()) augment(); printf("%d",ans); return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步