显然可以费用流来做,具体建图如下——

点集:源点,汇点,左边$n$​个工人,右边$n$​​​个设备

边集:源点向第$i$​个工人连$(1,a_{i})$​的边,第$i$​个设备向汇点连$(1,b_{i})$​​​的边,工人向可用的设备连$(1,0)$​的边

跑最小费用最大流,流量为$i$时的费用即为$i$时的答案

但注意到要跑$n$次spfa,每一次的最坏复杂度为$o(n^{3})$,显然无法通过

实际上,spfa即找到$x$和$y$,使得第$x$个工人和第$y$个设备都未被使用过,且第$x$个工人能流到第$y$个设备,在此基础上最大化$a_{x}+b_{y}$​,那么不妨手动来实现此功能

考虑按照$a_{i}$​​从大到小枚举左边未被使用过的的工人,并递归其能流到的点,求出其中设备$b_{i}$​的最大值

注意到当一个点已经被访问过,显然再访问一定不优于之前,单次复杂度即降为$o(n^{2})$​

每一个点只会被访问一次,因此复杂度瓶颈在于遍历边集,使用bfs来代替dfs,并对点分类讨论:

1.对于工人,其几乎到所有设备都有边,缺的仅有$o(m)$条限制和$o(n)$条之前流过的边,因此只需要遍历所有当前未被访问的点,并搜索其中可以访问的点

注意到一个未访问的点被遍历,要么被访问,要么属于$o(n+m)$​​条边之一,因此总复杂度即$o(m)$​​​

2.对于设备,其出边只有$o(n)$条之前流过的边的反向边,暴力遍历边集即可,总复杂度即$o(n)$

由此,单次复杂度降为$o(m)$​​,总复杂度即$o(nm)$​​,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 4005
4 #define ll long long
5 queue<int>q;
6 vector<int>v[N];
7 int t,n,m,x,y,a[N],b[N],id[N],visa[N],visb[N],vis[N],nex[N],pre[N<<1],mx[N],e[N][N];
8 ll ans;
9 bool cmp(int x,int y){
10 return a[x]>a[y];
11 }
12 int bfs(int k){
13 int s=0;
14 q.push(k);
15 vis[k]=1;
16 while (!q.empty()){
17 int k=q.front();
18 q.pop();
19 if (k<=n){
20 for(int i=nex[0],j=0;i<=n;j=i,i=nex[i])
21 if (e[k][i]){
22 pre[i+n]=k;
23 q.push(i+n);
24 nex[j]=nex[i],i=j;
25 }
26 }
27 else{
28 k-=n;
29 if ((!visb[k])&&(b[s]<b[k]))s=k;
30 for(int i=0;i<v[k].size();i++)
31 if (!vis[v[k][i]]){
32 pre[v[k][i]]=k+n;
33 q.push(v[k][i]);
34 vis[v[k][i]]=1;
35 }
36 }
37 }
38 return s;
39 }
40 int calc(){
41 int ans=0;
42 for(int i=1;i<=n;i++)vis[i]=0;
43 for(int i=0;i<=n;i++)nex[i]=i+1;
44 for(int i=1;i<=(n<<1);i++)pre[i]=0;
45 for(int i=1;i<=n;i++){
46 mx[i]=0;
47 if ((!visa[id[i]])&&(!vis[id[i]])){
48 mx[i]=bfs(id[i]);
49 if (mx[i])ans=max(ans,a[id[i]]+b[mx[i]]);
50 }
51 }
52 if (!ans)return 0;
53 for(int i=1;i<=n;i++)
54 if ((mx[i])&&(a[id[i]]+b[mx[i]]==ans)){
55 visa[id[i]]=1,visb[mx[i]]=1;
56 for(int lst=mx[i]+n,j=pre[lst];j;lst=j,j=pre[j]){
57 if (j<=n){
58 e[j][lst-n]=0;
59 v[lst-n].push_back(j);
60 }
61 else{
62 e[lst][j-n]=1;
63 for(int k=0;k<v[j-n].size();k++)
64 if (v[j-n][k]==lst){
65 v[j-n].erase(v[j-n].begin()+k);
66 break;
67 }
68 }
69 }
70 break;
71 }
72 return ans;
73 }
74 int main(){
75 scanf("%d",&t);
76 while (t--){
77 scanf("%d%d",&n,&m);
78 ans=0;
79 for(int i=1;i<=n;i++){
80 visa[i]=visb[i]=0;
81 v[i].clear();
82 }
83 for(int i=1;i<=n;i++)
84 for(int j=1;j<=n;j++)e[i][j]=1;
85 for(int i=1;i<=n;i++){
86 scanf("%d",&a[i]);
87 id[i]=i;
88 }
89 sort(id+1,id+n+1,cmp);
90 for(int i=1;i<=n;i++)scanf("%d",&b[i]);
91 for(int i=1;i<=m;i++){
92 scanf("%d%d",&x,&y);
93 e[x][y]=0;
94 }
95 for(int i=1;i<=n;i++){
96 int s=calc();
97 if (!s){
98 for(;i<=n;i++)printf("-1\n");
99 break;
100 }
101 ans+=s;
102 printf("%lld\n",ans);
103 }
104 }
105 return 0;
106 }

[hdu6978]New Equipments II的更多相关文章

  1. Leetcode 笔记 113 - Path Sum II

    题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...

  2. Leetcode 笔记 117 - Populating Next Right Pointers in Each Node II

    题目链接:Populating Next Right Pointers in Each Node II | LeetCode OJ Follow up for problem "Popula ...

  3. 函数式Android编程(II):Kotlin语言的集合操作

    原文标题:Functional Android (II): Collection operations in Kotlin 原文链接:http://antonioleiva.com/collectio ...

  4. 统计分析中Type I Error与Type II Error的区别

    统计分析中Type I Error与Type II Error的区别 在统计分析中,经常提到Type I Error和Type II Error.他们的基本概念是什么?有什么区别? 下面的表格显示 b ...

  5. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  6. [LeetCode] Guess Number Higher or Lower II 猜数字大小之二

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  7. [LeetCode] Number of Islands II 岛屿的数量之二

    A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...

  8. [LeetCode] Palindrome Permutation II 回文全排列之二

    Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...

  9. [LeetCode] Permutations II 全排列之二

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

随机推荐

  1. WCF服务调用超时错误:套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的。本地套接字超时是“00:05:30”(已解决)

    问题: 线上正式环境调用WCF服务正常,但是每次使用本地测试环境调用WCF服务时长就是出现:套接字连接已中止.这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的.本地套接字超 ...

  2. nginx访问权限问题

    1.问题 server { listen 8011; server_name test.cn; location ~ \.php?.*$ { root /home/zhj/; #fastcgi_pas ...

  3. ansible远程运维操作

    1.command 用于查看文件内容,查看磁盘,内存,启动命令等纯命令信息 ansible portal -m command -a "cat /test1/test"2.ping ...

  4. PAT (Basic Level) Practice (中文)1031 查验身份证 (15分)

    1031 查验身份证 (15分) 一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为: {7,9,10,5,8,4,2 ...

  5. for...in和Object.keys()区别

    区别: for in 用来枚举对象的属性,某些情况下,可能按照随机顺序遍历数组元素 object.keys() 可以返回对象属性为元素的数组,数组中属性名顺序和for in比那里返回顺序一样 ---f ...

  6. 天脉2(ACoreOS653)操作系统学习01

    天脉2(ACoreOS653)操作系统学习01 由于我的毕业设计涉及相关嵌入式操作系统,故最近学了学天脉2操作系统. 一.ARINC653标准 1.ARINC653标准是什么? ARINC 653 : ...

  7. [软工顶级理解组] Alpha阶段项目展示

    目录 团队成员 软件介绍 项目简介 预期典型用户 功能描述 预期目标用户数 用户反馈 团队管理 分工协作 项目管理 取舍平衡 代码管理 程序测试 代码规范 文档撰写 继续开发指导性 用户沟通 需求分析 ...

  8. OO第四单元作业总结及课程总结

    一.本单元作业架构设计 1.第一次作业 本单元首次接触到UML以及相关概念,在面对第一次作业时首先花了很大功夫去阅读官方接口中各种UmlElement的代码,才理解了输入的模型元素中各属性的含义.总的 ...

  9. 基于docker-compose搭建sonarqube代码质量检测平台

    一.需求 在我们开发的过程中,难免有时候代码写的不规范,或存在一些静态的bug问题,这个时候一个良好的代码检查工具就很有必要,而sonarqube正好可以满足整个要求. 二. docker-compo ...

  10. 设计的MOS管三极管简单开关电路驱动能力不够2

    设计的MOS管三极管简单开关电路驱动能力不够 [复制链接]     lxizj 9 主题 454 帖子 1783 积分 四级会员(40) 积分 1783 发消息 16#   发表于 2012-4-23 ...