列表

详情


NC50788. 通信

描述

n个排成一列的哨站要进行通信。第i个哨站的频段为a_i
每个哨站i需要选择以下二者之一:
  • 直接连接到控制中心,代价为W;
  • 连接到前面的某个哨站j(j<i),代价为
每个哨站只能被后面的至多一个哨站连接。
请你求出最小可能的代价和。

输入描述

第1行两个自然数n,W,分别表示哨站个数和连接到控制中心的代价;
第2行n个由空格分隔的自然数依次表示每个哨站的频段。

输出描述

输出1行1个自然数表示答案。

示例1

输入:

6 7
8 4 6 1 3 0

输出:

23

说明:

如果用0表示控制中心,最优方案中每个哨站向前连接的哨站依次为0,0,1,2,3,4。

示例2

输入:

8 4
0 4 2 6 1 5 3 7

输出:

18

示例3

输入:

100 531063
868483 100818 599407 704404 691662 782990 647491 218122 906201 12145 213363 595660 501106 833711 287575 619422 507402 420930 732686 870198 446826 342144 292424 902348 925183 212446 955363 378479 596174 309751 998582 455254 992178 633810 778478 946660 884959 402342 385986 494727 398344 203903 470147 725470 227967 913015 951620 354755 197540 876065 52845 937399 823696 923941 600611 770238 296406 287789 848913 469593 641739 79570 275816 380754 95083 729424 35970 951734 833884 510971 854659 580018 428193 939020 990682 680852 886057 204917 230803 764275 803010 226704 709978 844136 709941 869203 634743 296404 480722 605047 803899 484430 637481 230117 731240 308602 309554 696800 755081 682448

输出:

7292623

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1594ms, 内存消耗: 2872K, 提交时间: 2020-10-08 22:06:42

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=5e4+5,M=8e6+5;
const LL Inf=1e18;
struct mincostmaxflow{
	struct Edge{int to,f,w,nxt;}e[M];
	int s,t,fst[N],tote,pre[N],from[N],q[N<<10],hd,tl;
	LL dis[N],mi[N];bool inq[N];
	void adde(int u,int v,int f,int w){
		e[++tote]=(Edge){v,f,w,fst[u]};fst[u]=tote;
		e[++tote]=(Edge){u,0,-w,fst[v]};fst[v]=tote;
	}
	void init(int ns,int nt){
		s=ns;t=nt;
		memset(fst,-1,sizeof(fst));tote=1;
	}
	bool spfa(){
	    for(int i=1;i<N;i++)dis[i]=Inf,inq[i]=false;
	    dis[s]=0;q[hd=tl=1]=s;inq[s]=true;mi[s]=Inf;
	    while(hd<=tl){
	    	if(hd<tl&&dis[q[hd]]>dis[q[tl]])swap(q[hd],q[tl]);
	        int u=q[hd++];inq[u]=false;
	        for(int i=fst[u],v,w;~i;i=e[i].nxt)if(e[i].f){
	            v=e[i].to;w=e[i].w;
	            if(dis[v]>dis[u]+w){
	                dis[v]=dis[u]+w;mi[v]=min(mi[u],(LL)e[i].f);pre[v]=i;from[v]=u;
	                if(!inq[v])inq[v]=true,q[++tl]=v; 
	            }
	        }
	    }
	    return dis[t]<Inf;
	}
	LL EK(){
		LL res=0;
		while(spfa()){
			for(int i=t;i!=s;i=from[i])e[pre[i]].f-=mi[t],e[pre[i]^1].f+=mi[t];
			res+=(LL)mi[t]*dis[t];
		}
		return res;
	}
}F;
int n,w,s,t,a[N],in[N],out[N],b[N],tot;
void cdq(int l,int r){
	if(l==r)return;
	int mid=(l+r)>>1,len=0;
	cdq(l,mid);cdq(mid+1,r);
	for(int i=l;i<=r;i++)b[++len]=a[i];
	sort(b+1,b+len+1);len=unique(b+1,b+len+1)-b-1;
	for(int i=1;i<len;i++)F.adde(tot+i,tot+i+1,1e9,b[i+1]-b[i]),F.adde(tot+i+1,tot+i,1e9,b[i+1]-b[i]);
	for(int i=l,x;i<=r;i++){
		x=lower_bound(b+1,b+len+1,a[i])-b;
		if(i<=mid)F.adde(tot+x,out[i],1,0);else F.adde(in[i],tot+x,1,0);
	}
	tot+=len;
}
int main(){
	scanf("%d%d",&n,&w);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),in[i]=i,out[i]=i+n;
	F.init(s=out[n]+1,t=out[n]+2);tot=t;
	for(int i=1;i<=n;i++)F.adde(s,in[i],1,0),F.adde(out[i],t,1,0),F.adde(in[i],t,1,w);
	cdq(1,n);
	printf("%lld\n",F.EK());
	return 0;
}

上一题