SCU 4584 tarjan+最大权闭合子图

把每个点的点权当做是W[i]-V[i] 题目一眼是最大权闭合子图 但是可能会有重边自环和环 需要先搞成简单图 再tarjan缩点 缩点后就是裸的最大权闭合子图
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = ;
const int MAXM = ;
const ll INF = 200000000050000LL;
int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << ], nxt[MAXM << ], ed, S, T;
ll f[MAXM << ];
inline void addedge2(int u, int v) {
to[++ed] = v;
nxt[ed] = Head[u];
Head[u] = ed;
return;
}
inline void addedge(int u, int v, ll cap) {
to[++ed] = v;
nxt[ed] = Head[u];
Head[u] = ed;
f[ed] = cap;
to[++ed] = u;
nxt[ed] = Head[v];
Head[v] = ed;
f[ed] = ;
return;
}
inline bool BFS() {
int u;
memset(lev, -, sizeof(lev));
queue<int>q;
lev[S] = ;
q.push(S);
while (q.size()) {
u = q.front();
q.pop();
for (int i = Head[u]; i; i = nxt[i])
if (f[i] && lev[to[i]] == -) {
lev[to[i]] = lev[u] + ;
q.push(to[i]);
/*
if (to[i] == T)
{
return 1;
}
magic one way optimize
*/
}
}
memcpy(cur, Head, sizeof Head);
return lev[T] != -;
}
inline ll DFS(int u, ll maxf) {
if (u == T || !maxf) {
return maxf;
}
ll cnt = , tem;
for (int &i = cur[u]; i; i = nxt[i])
if (f[i] && lev[to[i]] == lev[u] + ) {
tem = DFS(to[i], min(maxf, f[i]));
maxf -= tem;
f[i] -= tem;
f[i ^ ] += tem;
cnt += tem;
if (!maxf) {
break;
}
}
if (!cnt) {
lev[u] = -;
}
return cnt;
}
ll Dinic() {
ll ans = ;
while (BFS()) {
ans += DFS(S, INF);
}
return ans;
}
void init(int SS, int TT) {
ed = ;
S = SS;
T = TT;
return;
}
//Directed tarjan(without repeat edge)
int deep, colorsum = ;
int top;/*sta目前的大小*/
int dfn[MAXN], color[MAXN], low[MAXN];
int sta[MAXN];//存着当前所有可能能构成强连通分量的点
bool visit[MAXN];//表示一个点目前是否在sta中
int cnt[MAXN];//各个强连通分量中含点的数目
ll valsum[MAXN];
void tarjan(int x) {
dfn[x] = ++deep;
low[x] = deep;
visit[x] = ;
sta[++top] = x;
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (!dfn[v]) {
tarjan(v);
low[x] = min(low[x], low[v]);
} else {
if (visit[v]) {
low[x] = min(low[x], low[v]);
}
}
}
if (dfn[x] == low[x]) {
color[x] = ++colorsum;
visit[x] = ;
while (sta[top] != x) {
color[sta[top]] = colorsum;
visit[sta[top--]] = ;
}
top--;
}
}
ll w[MAXN];
pair<int, int> Edge[MAXM];
map<pair<int, int>, int> mp;
int main() {
int n, m, x;
int u, v, c;
int TNT;
scanf("%d", &TNT);
while (TNT--) {
mp.clear();
scanf("%d %d", &n, &m);
top = colorsum = ;
for (int i = ; i <= n + ; i++) {
visit[i] = dfn[i] = low[i] = cnt[i] = color[i] = Head[i] = ;
valsum[i] = ;
}
ed = ;
for (int i = ; i <= n; i++) {
scanf("%lld", &w[i]);
}
for (int i = ; i <= n; i++) {
scanf("%d", &x);
w[i] -= x;
}
for (int i = ; i <= m; i++) {
scanf("%d %d", &u, &v);
if (u == v || mp[make_pair(u, v)]) {
Edge[i].first = u, Edge[i].second = u;
continue;
}
mp[make_pair(u, v)] = ;
Edge[i].first = u, Edge[i].second = v;
addedge2(u, v);
}
for (int i = ; i <= n; i++) {
if (!dfn[i]) {
tarjan(i);
}
}
for (int i = ; i <= n; i++) {
valsum[color[i]] += w[i];
}
init(, n + );
for (int i = ; i <= n + ; i++) {
Head[i] = ;
}
ll anser = ;
for (int i = ; i <= colorsum; i++) {
if (valsum[i] > ) {
anser += valsum[i];
addedge(S, i, valsum[i]);
} else if (valsum[i] < ) {
addedge(i, T, -valsum[i]);
}
}
for (int i = ; i <= m; i++) {
u = Edge[i].first;
v = Edge[i].second;
if (color[u] == color[v]) {
continue;
}
addedge(color[u], color[v], INF);
}
cout << anser - Dinic() << endl;
}
return ;
}
SCU 4584 tarjan+最大权闭合子图的更多相关文章
- bzoj 1565 [NOI2009]植物大战僵尸【tarjan+最大权闭合子图】
一上来以为是裸的最大权闭合子图,上来就dinic -然后没过样例.不得不说样例还是非常良心的给了一个强连通分量,要不然就WA的生活不能自理了 然后注意到有一种特殊情况:每个植物向他保护的植物连边(包括 ...
- bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan
bzoj1565: [NOI2009]植物大战僵尸 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1565 思路 很容易的想到最大权闭合子图 ...
- BZOJ1565 [NOI2009]植物大战僵尸 【最大权闭合子图 + tarjan缩点(或拓扑)】
题目 输入格式 输出格式 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. 输入样例 3 2 10 0 20 0 -10 0 -5 1 0 0 100 ...
- HDU4971 A simple brute force problem.(强连通分量缩点 + 最大权闭合子图)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4971 Description There's a company with several ...
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)
题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ...
- HDU 3879 Base Station(最大权闭合子图)
经典例题,好像说可以转化成maxflow(n,n+m),暂时只可以勉强理解maxflow(n+m,n+m)的做法. 题意:输入n个点,m条边的无向图.点权为负,边权为正,点权为代价,边权为获益,输出最 ...
- [BZOJ 1497][NOI 2006]最大获利(最大权闭合子图)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1497 分析: 这是在有向图中的问题,且边依赖于点,有向图中存在点.边之间的依赖关系可以 ...
- HDU5855 Less Time, More profit(最大权闭合子图)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5855 Description The city planners plan to build ...
随机推荐
- 【HANA系列】SAP HANA SQL IFNULL和NULLIF用法与区别
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL IFN ...
- LeetCode.1170-比较字符串中最小字符的出现频率(Compare Strings by Frequency of the Smallest Char)
这是小川的第412次更新,第444篇原创 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第263题(顺位题号是1170).在一个非空字符串s上定义一个函数f(s),该函数计算s中最小字 ...
- 抄录的Linux命令
daemon daemon 有一个很高大上的中文名字,叫 守护进程 . 有句话是这么说的,如果 Unix 中没有了守护进程,那么 Unix 就不会是相同的. 它很有个性,是一个运行在后台且不受终端控制 ...
- mysql数据库之函数、流程控制
函数 注意与存储过程的区别,mysql内置的函数只能在sql语句中使用! 参考博客:http://www.cnblogs.com/linhaifeng/articles/7495918.html#_l ...
- python之迭代器、可迭代对象、生成器、生成器对象、枚举类型
迭代器 # 迭代器:循环反馈的容器(集合类型)# -- 不同于索引取值,但也可以循环的从容器对象中从前往后逐个返回内部的值# 优点:不依赖索引,完成取值# 缺点:不能计算长度,不能指定位取值(只能从 ...
- python3正则表达式详细用法示例
转载自:https://www.runoob.com/python3/python3-reg-expressions.html
- linux 静态库 ar命令用法
当我们的程序中有经常使用的模块,而且这种模块在其他程序中也会用到,这时按照软件重用的思想,我们应该将它们生成库,使得以后编程可以减少开发代码量.这里介绍命令ar,用来对库操作. 1.ar基本用法 ar ...
- 栈与队列基本操作 Java实现
一.顺序栈 //数组实现顺序栈 public class OrderStack { private String[] elem; private int top; OrderStack(int k) ...
- Netty源码之解码中两种数据积累器(Cumulator)的区别
上一篇随笔中已经介绍了解码核心工作流程,里面有个数据积累器的存在(Cumulator),其实解码中有两种Cumulator,那他们的区别是什么呢? 还是先打开ByteToMessageDecoder的 ...
- python------模块基础【第二部分-time】------
一.time UTC/GMT:世界时间 本地时间:本地时区时间 python中时间日期格式化符号: %y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01- ...