zoj 3165 Party of 8g (最大点权独立集)
来源:互联网 发布:数据库一般多大内存 编辑:程序博客网 时间:2024/06/06 08:26
As all you know, DD is a hospitable person. On Saint Valentine's Day, DD is going to arrang a party for girls and boys. However, as you may don't know, DD hate the so-called "8g" relationship. So, he will not invite a boy and a girl who have 8g at the same time.
DD's friends are M boys (labeled 1..M) and N girls (labeled 1..N), and each of them has a "lovely value". Now, DD want to invite some of them, satisfying that no 8g exists among invited people, and the total lovely value of all the invited people can be maximal.
Input
Multiple test cases, each cases consists of three parts.
First part, one line, three integers M, N and S.
Second part, two lines. First line, M integers, boys' lovely values from the 1st to the Mth. Second line, N integers, girls' lovely values from the 1st to the Nth.
Third part, S lines. Each line consists of two integers X and Y, means that the boy X and the girl Y have 8g.
One blank line between test cases.
Output
For each test case, your output should include three parts.
First part, one line, three integers X, A and B. X is the maximal total lovly value. A and B are the numbers of boys and girls invited.
Second part, one line, A integers, labels of the invited boys.
Third part, one line, B integers, labels of the invited girls.
If multiple solutions exist, output any of them.
Data Restriction
0 <= M, N <= 100; 0 <= S <= M*N.
1 <= lovely value <= 1024.
Sample Input
5 5 101 3 5 7 92 4 6 8 101 45 32 43 51 12 41 23 41 55 5
Sample Output
37 1 541 2 3 4 5
Author: CUI, Tianyi
Source: ZOJ Monthly, February 2009
求二分图的最大点权独立集, 等于总权值 - 最小点权覆盖集。最小点权覆盖集就是最小割。最小割的方案是在求过最大流的残留网络中,从s出发遍历所有的点,构成集合S。再根据S判断。
#include<cstdio>#include<map>#include<queue>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<list>#include<set>#include<cmath>using namespace std;const int maxn = 1e5 + 5;const int INF = 1e9;const double eps = 1e-6;typedef unsigned long long ULL;typedef long long LL;typedef pair<int, int> P;#define fi first#define se secondstruct Edge { int from, to, cap, flow;};struct Dinic { int n, m, s, t; vector<Edge> edges; // 边数的两倍 vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[maxn]; // BFS使用 int d[maxn]; // 从起点到i的距离 int cur[maxn]; // 当前弧指针 void ClearAll(int n) { for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void ClearFlow() { for(int i = 0; i < edges.size(); i++) edges[i].flow = 0; } void AddEdge(int from, int to, int cap) { //cout << from << ' ' << to << ' ' << cap << endl; 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; } vector<int> boy, girl; void get_ans(int a, int b){ boy.clear();girl.clear(); int vis[maxn]; memset(vis, 0, sizeof vis); queue<int> q; q.push(0); while(!q.empty()){ int pos = q.front();q.pop(); for(int i = 0;i < G[pos].size();i++){ Edge& e = edges[G[pos][i]]; if(e.cap > e.flow && !vis[e.to]){ vis[e.to] = 1; q.push(e.to); } } } for(int i = 1;i <= a;i++){ if(vis[i]==1) boy.push_back(i); } for(int i = a+1;i <= a+b;i++){ if(vis[i]==0) girl.push_back(i-a); } }};Dinic g;int main(){ int a, b, m; while(scanf("%d%d%d", &a, &b, &m) != EOF){ g.ClearAll(a+b+5); int source = 0, sink = a+b+1; int total = 0; for(int i = 1;i <= a;i++){ int x; scanf("%d", &x); total += x; g.AddEdge(source, i, x); } for(int i = 1;i <= b;i++){ int x; scanf("%d", &x); total += x; g.AddEdge(i+a, sink, x); } while(m--){ int x, y; scanf("%d%d", &x, &y); g.AddEdge(x, a+y, INF); } cout << total-g.Maxflow(source, sink); g.get_ans(a, b); cout << ' ' << g.boy.size() << ' ' << g.girl.size() << endl; int bsize = g.boy.size(); for(int i = 0;i < bsize-1;i++){ cout << g.boy[i] << ' '; } if(bsize>=1) cout << g.boy[bsize-1]; cout << endl; int gsize = g.girl.size(); for(int i = 0;i < gsize-1;i++){ cout << g.girl[i] << ' '; } if(gsize>=1) cout << g.girl[gsize-1]; cout << endl; } return 0;}
- ZOJ 3165 Party of 8g (最大点权独立集)
- zoj 3165 Party of 8g (最大点权独立集)
- zoj 3165 (最小割,最大点权独立集)
- zoj 3165 (最小割,最大点权独立集)
- zoj 3165(二分图最大点权独立)
- zoj 3760 Treasure Hunting(最大点权独立集)
- ZOJ 3760 Treasure Hunting 最大点权独立集
- POJ 2771 Guardian of Decency(最大独立点集)
- 最大流最小割(最大点权独立集)
- 最大流最大点权独立集
- ZOJ 3760 - Treasure Hunting(网络流‘最小割’最大点权独立集)
- UVa 1220 - Party at Hali-Bula(最大独立集)
- hdu1520 Anniversary party(最大独立集 树形dp)
- UVa-1220 Party at Hali-Bula (最大独立集)
- zoj - 1137 - Girls and Boys(二分图最大独立点集)
- UVa live3415Guardian of Decency(二分最大匹配之最大独立点集)
- 最大点独立集
- poj 3342 Party at Hali-Bula 判断二分图最大点独立集是否唯一
- iOS-Quartz2D 之 画图预览笔记
- 十五个经典算法研究与总结、目录+索引
- Linux驱动中,probe函数何时被调用
- java中string字符串拼装性能比较
- MDsun被精选为艾美奖Emmy Award
- zoj 3165 Party of 8g (最大点权独立集)
- C++Pimer学习笔记
- 分享按钮
- 整洁代码之一:决定开始阅读Clean Code
- maven资源文件.properties的引用
- IS_ERR()说明
- oracle 11g中的 oracle restart特性
- JSF 2.0 中定义受管 Bean 的四种方式
- 在树莓派(Debian系统)上安装wxPython