zoukankan      html  css  js  c++  java
  • P6122-[NEERC2016]Mole Tunnels【模拟费用流】

    正题

    题目链接:https://www.luogu.com.cn/problem/P6122


    题目大意

    给出(n)个点的一棵满二叉树,每个点有容量(c_i)(m)次从(p_i)处加一只仓鼠然后求每只仓鼠都到一个点的最短路径长度和。

    (1leq nleq 10^5)


    解题思路

    模拟费用流的思想就是....模拟费用流(字面意思

    因为是满二叉树,我们对于每个节点维护一个往下最短的路径还有容量的节点(需要注意的是路径上如果流量是反向的话长度要是(-1))。

    然后暴力更新这条路径上的流量,再更新一下刚刚那个东西就好了。

    时间复杂度(O(nlog n))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=4e5+10;
    int n,m,c[N],dis[N],pos[N],flow[N],ans;
    void updata(int x){
    	dis[x]=2147483647/3;pos[x]=0;
    	if(c[x])dis[x]=0,pos[x]=x;
    	if(dis[x*2]+(flow[x*2]>0?-1:1)<dis[x])
    		dis[x]=dis[x*2]+(flow[x*2]>0?-1:1),pos[x]=pos[x*2];
    	if(dis[x*2+1]+(flow[x*2+1]>0?-1:1)<dis[x])
    		dis[x]=dis[x*2+1]+(flow[x*2+1]>0?-1:1),pos[x]=pos[x*2+1];
    	return;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	memset(dis,0x3f,sizeof(dis));
    	for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    	for(int i=n;i>=1;i--)updata(i);
    	for(int i=1;i<=m;i++){
    		int p;scanf("%d",&p);
    		int x=0,cost=2147483647/3,now=0;
    		for(int y=p;y!=0;y>>=1){
    			if(now+dis[y]<cost)
    				cost=now+dis[y],x=y;
    			now+=(flow[y]<0?-1:1);
    		}
    		ans+=cost;
    		for(int y=p;y!=x;y>>=1)flow[y]++;
    		for(int y=pos[x];y!=x;y>>=1)flow[y]--;
    		c[pos[x]]--;
    		for(int y=pos[x];y!=x;y>>=1)updata(y);
    		for(int y=p;y!=0;y>>=1)updata(y);
    		printf("%d ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Win32 服务进程和单实例实现
    Win32开发(命令行参数处理)
    动态链接库
    Poco 配置文件读取
    Delphi 窗口消息
    【原创】用phantomjs爬取网页数据
    【原创】搭建spark环境二
    【原创】搭建spark环境
    python爬虫——抓取电影天堂电影信息
    【学习笔记】Python 小练习—数据挖掘
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14979185.html
Copyright © 2011-2022 走看看