zoukankan      html  css  js  c++  java
  • 埃蒙的时空航道

    埃蒙的时空航道

    题目链接:http://dutacm.club:7217/codesheaven/problem.php?id=1082

    题目大意:有$n$个星球,每个星球有$p_i$个军队,$x$星球上的军队最多可迁移不超过$c$个军队到$y$星球上($x leq y$).现已知一段时间后各个星球会遇到$s_i$个敌人袭击,问最多能干掉多少敌人.

    网络流+优先队列优化dp

    翻了入门经典好好看了发网络流,比网上参差不齐的blog好太多了= =,也是总算明白了.

    最大流最小割定理:

    若将所有顶点分成两个点集$S$和$T$,其中源点$s$在$S$中,汇点$t$在$T$中,那么$S$就被称为点割集.

    如果将"起点在$S$中,终点在$T$中"的所有有向边删除,则不存在一条从源点$s$到汇点$t$的路径,将这样一组边的集合称为一个$s-t$割,它的容量定义为$c(S,T)=sum_{u in S,v in T}c(u,v)$,称为割值.

     对于任意的$s-t$流$f$和任意$s-t$割$(S,T)$,有$|f| leqslant c(S,T)$,特别地,最小割等于最大流.


    根据题意,很自然可以构造网络流模型:建立一个虚源点,向每个星球连一条容量为$p_i$的有向边,每个编号较小的星球向编号较大的星球连一条容量为$c$的有向边,每个星球向虚汇点连一条容量为$s_i$的有向边.最大流复杂度为$O(n imes E^2)$,显然不合适,转向求最小割.因此题网络较为规则,最小割可用DP求解.

    定义状态$dp[i][j]$为前$i$个点构成的网络里,点割集包含$j$个点的最小割.则状态转移方程为:

    $dp[i][j]=min(dp[i-1][j-1]+s[i],dp[i-1][j]+p[i]+j imes c)$.

    复杂度为$O(n^2)$,仍不足以通过此题.

    注意到,设$a_t otin S$,$S'={a_i|a_i in S$且$i leq t}$,$|S|=k$,$|S'|=x$,则此时割值为$A=F+p_i+cx$.

    当$a_t$被加入到$S$中时,割值变化为$B=F+s_i+c[n-i-(k-x)]$.于是当割集加入一个节点$a_t$,割值会增加$B-A=s_i-p_i+c(n-i-k)=s_i-p_i+c(n-i)-ck$.

    令$w_i=s_i-p_i+c(n-i)$,每次加入使$w_i$最小的点到点割集中,所得的割值一定最小.

    故可以用优先队列维护$w_i$的最小值,使得复杂度降为$O(nlgn)$.

    代码如下:

     1 #include <iostream>
     2 #include <queue>
     3 #define N 100005
     4 using namespace std;
     5 typedef long long ll;
     6 ll n,c,p[N],s[N],temp,ans;
     7 priority_queue<ll>q;
     8 int main(void){
     9     std::ios::sync_with_stdio(false);
    10     cin>>n>>c;
    11     for(int i=1;i<=n;++i)cin>>p[i],temp+=p[i],ans=temp;
    12     for(int i=1;i<=n;++i)cin>>s[i];
    13     for(int i=1;i<=n;++i)q.push(-(s[i]-p[i]+(n-i)*c));
    14     for(int i=0;i<n;++i){
    15         ll t=q.top();q.pop();
    16         temp-=t+i*c;
    17         ans=min(ans,temp);
    18     }
    19     cout<<ans<<"
    ";
    20 }
  • 相关阅读:
    VS2012 窗口布局, update1 和 英语语言包 离线安装方法
    C/C++ 笔记
    MFC学习笔记
    理解虚基类、虚函数与纯虚函数的概念
    ffmpeg使用
    gif制作 & word2007插入gif
    WIN8电脑开机怎么进入安全模式啊?
    vs2012 win8 64 visual assistX 中文 ??
    21 获取文件大小的方法
    20 线程中添加超时的方法
  • 原文地址:https://www.cnblogs.com/barrier/p/6528516.html
Copyright © 2011-2022 走看看