题目链接:点击打开链接

思路:

看这些限制条件, 我们很容易想到二分图,  两个公司分别建立两列结点, 表示每个订单。  关键是每个资源只能为一个公司所有,而且一旦买了一个订单, 所有资源都要全买。

根据最小割, 我们如果在冲突的订单(存在相同资源)间连一条容量INF的边, 那么割掉的边就是受益最小的, 最终求出来的是最小受益,  用总的减去最小受益就行了。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 6000 + 10;
int T,n,m;
struct Edge {int from, to, cap, flow;
};
bool operator < (const Edge& a, const Edge& b) {return a.from < b.from || (a.from == b.from && a.to < b.to);
}
struct Dinic {int n, m, s, t;        // 结点数, 边数(包括反向弧), 源点编号, 汇点编号vector<Edge> edges;    // 边表, edges[e]和edges[e^1]互为反向弧vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号bool vis[maxn];        // BFS使用int d[maxn];           // 从起点到i的距离int cur[maxn];         // 当前弧指针
void init(int n) {for(int i = 0; i < n; i++) G[i].clear();edges.clear();
}
void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});m = edges.size();G[from].push_back(m-2);G[to].push_back(m-1);
}
bool BFS() {memset(vis, 0, sizeof(vis));queue<int> Q;Q.push(s);vis[s] = 1;d[s] = 0;while(!Q.empty()) {int x = Q.front(); Q.pop();for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(!vis[e.to] && e.cap > e.flow) {  //只考虑残量网络中的弧vis[e.to] = 1;d[e.to] = d[x] + 1;Q.push(e.to);}}}return vis[t];
}
int DFS(int x, int a) {if(x == t || a == 0) return a;int flow = 0, f;for(int& i = cur[x]; i < G[x].size(); i++) {  //上次考虑的弧Edge& e = edges[G[x][i]];if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {e.flow += f;edges[G[x][i]^1].flow -= f;flow += f;a -= f;if(a == 0) break;}}return flow;
}
int Maxflow(int s, int t) {this->s = s; this->t = t;int flow = 0;while(BFS()) {memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}return flow;}
}g;
int u, vll[maxn], v, c, kase = 0, val[maxn][35], cnt[maxn];
bool vis[300010];
char s[maxn];
int main() {scanf("%d",&T);while(T--) {scanf("%d", &n);int tot = 0;memset(cnt, 0, sizeof(cnt[0])*(n+m+5));for(int i = 1; i <= n; i++) {scanf("%d", &vll[i]);tot += vll[i];getchar();gets(s);int len = strlen(s), cur = 0;memset(val[i], 0, sizeof(val[i]));for(int j = 0; j < len; j++) {if(s[j] == ' ') cnt[i]++;else val[i][cnt[i]] = val[i][cnt[i]]*10 + s[j]-'0';}}scanf("%d", &m);int src = 0, stc = n+m+1;g.init(n+m + 5);for(int i = 1; i <= n; i++) g.AddEdge(src, i, vll[i]);for(int i = n+1; i <= n+m; i++) {scanf("%d", &v);tot += v;g.AddEdge(i, stc, v);getchar();gets(s);int len = strlen(s), cur = 0;memset(val[i], 0, sizeof(val[i]));for(int j = 0; j < len; j++) {if(s[j] == ' ') cnt[i]++;else val[i][cnt[i]] = val[i][cnt[i]]*10 + s[j]-'0';}}for(int i = 1; i <= n; i++) {for(int k = 0; k <= cnt[i]; k++) {int v = val[i][k];vis[v] = true;}for(int j = n+1; j <= n+m; j++) {bool ok = false;for(int k = 0; k <= cnt[j]; k++) {int v = val[j][k];if(vis[v]) {ok = true; break;}}if(ok) g.AddEdge(i, j, INF);}for(int k = 0; k <= cnt[i]; k++) {int v = val[i][k];vis[v] = false;}}printf("Case %d:\n", ++kase);printf("%d\n", tot - g.Maxflow(src, stc));if(T) printf("\n");}return 0;
}

UVA 1212 - Duopoly(最小割)相关推荐

  1. LA 3487 Duopoly 最小割

    传送门:LA 3487 Duopoly 题目大意:T公司和M公司想向政府申请一些资源的使用权.每一项申请包含一个资源列表和该公司愿意支付的金额.如果该申请得到批准,该公司将得到列表中所有资源的使用权. ...

  2. UVA - 10480 Sabotage 最小割,输出割法

    UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解: ...

  3. UVA - 10480 Sabotage(最小割-最大流+输出割边)

    题目链接:点击查看 题目大意:给出一张无向图,1为起点,2为终点,删除每条边都需要权值wi,题目需要求将起点与终点分割为两个部分的最小花费,并且输出方案 题目分析:如果不让输出方案的话就是一个裸的最大 ...

  4. Sabotage UVA - 10480 (最小割+求最小割去掉的具体边+ISAP)

    传送门 题意:给定n个点,m条带权无向边,源点s=1,汇点t=2.去掉一些边之后使s,t不连通,求去掉的这些边(而且还要满足去掉的边权和是所有答案中最小的--最小割). n<=50,m<= ...

  5. UVA 1515 - Pool construction(最小割)

    题目链接 https://cn.vjudge.net/problem/UVA-1515 [题意] 输入一个h行w列的字符矩阵,草地用'#'表示,洞用'.'表示,可以把一个草地换成洞,费用为d,也可以把 ...

  6. Pool construction UVA - 1515 最小割模型

    传送门 文章目录 题意: 思路: 题意: 给你一个n∗mn*mn∗m的矩阵,包含字符#和.,将#变成.的代价是ddd,将.变成#的代价是fff,让后将#和.隔开的代价是bbb,现在让你用最小的代价将# ...

  7. UVA - 10480 Sabotage 输出最小割方案

    题目链接 https://vjudge.net/problem/UVA-10480 题意 无向图求最小割的方案 思路 最小割部分是模版,问题在于最小割的方案如何输出. 首先根据最小割最大流定理,我们跑 ...

  8. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  9. [学习笔记]最小割之最小点权覆盖最大点权独立集

    最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...

  10. POJ 1966 Cable TV Network【无向图点连通度 最小割 E-K算法求最大流】

    题目描述: 给你一个无向图,问你最少删掉几个点,使这个图成不连通. 解题报告: 概念 (1)一个具有 N 个顶点的图,在去掉任意 k-1 个顶点后 (1<=K<=N) 所得的子图仍连通, ...

最新文章

  1. 【SICP练习】91 练习2.64
  2. 水下图像处理算法Sea-thru
  3. 爬虫学习笔记(八)—— Scrapy框架(三):CrawSpider模板
  4. AES加密 — 详解
  5. 第十八章 12判断string类型字符串是否为空
  6. Team Foundation Server安装指南
  7. spring boot学习(5): 进程exit code自定义
  8. 火狐firefox插件配合scrapy,注意tbody会导致empty
  9. 分享非常有用的Java程序(关键代码)(七)---抓屏程序
  10. 项目常用工具类整理(二)--ckeditor的引用
  11. 【Django 2021年最新版教程33】Jmeter如何进行性能测试
  12. win7小工具打不开_有了这个工具,小白也能设置一键网络共享文件夹与打印机...
  13. Andorid Activity的本质是什么
  14. odoo 菜单前台无法显示
  15. 05--SpringBoot之上传文件
  16. 【Python 数据科学】分组group by基础
  17. 2022.3.2复盘
  18. 【自动化】国内自动化与信息化产业仍有十年以上的产业繁荣;非标自动化业务你离BOSS只差一个认知
  19. 如何在MS Project中进行挣值分析
  20. 单片机之FPGA选修部分基础了解

热门文章

  1. 免费WiFi上网软件是什么?怎么用?
  2. 【微信自动续费】委托代扣接口常见问题QA
  3. Linux服务器清理磁盘
  4. python如何筛选数据_Python如何用filter函数筛选数据
  5. 问题adb remount提示Devices Locked
  6. CPU中控制器的功能
  7. Spring 5.0.3.RELEASE中的 Kotlin 语言等支持
  8. vnc远程控制软件,五款良心推荐的vnc远程控制软件
  9. 移动硬盘备份linux系统盘,Ubuntu 系统备份到移动硬盘(tar) 还原到另一台电脑
  10. 解决photoshop cc在4K分辨率下字体过小。