Petya and Graph/最大权闭合子图、最小割
原题地址:https://codeforces.com/contest/1082/problem/G
2 seconds
256 megabytes
standard input
standard output
Petya has a simple graph (that is, a graph without loops or multiple edges) consisting of nn vertices and mm edges.
The weight of the ii-th vertex is aiai.
The weight of the ii-th edge is wiwi.
A subgraph of a graph is some set of the graph vertices and some set of the graph edges. The set of edges must meet the condition: both ends of each edge from the set must belong to the chosen set of vertices.
The weight of a subgraph is the sum of the weights of its edges, minus the sum of the weights of its vertices. You need to find the maximum weight of subgraph of given graph. The given graph does not contain loops and multiple edges.
The first line contains two numbers nn and mm (1≤n≤103,0≤m≤1031≤n≤103,0≤m≤103) - the number of vertices and edges in the graph, respectively.
The next line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) - the weights of the vertices of the graph.
The following mm lines contain edges: the ii-e edge is defined by a triple of integers vi,ui,wivi,ui,wi (1≤vi,ui≤n,1≤wi≤109,vi≠ui1≤vi,ui≤n,1≤wi≤109,vi≠ui). This triple means that between the vertices vivi and uiui there is an edge of weight wiwi. It is guaranteed that the graph does not contain loops and multiple edges.
Print one integer — the maximum weight of the subgraph of the given graph.
4 5
1 5 2 2
1 3 4
1 4 4
3 4 5
3 2 2
4 2 2
8
3 3
9 7 8
1 2 1
2 3 2
1 3 3
0
In the first test example, the optimal subgraph consists of the vertices 1,3,41,3,4 and has weight 4+4+5−(1+2+2)=84+4+5−(1+2+2)=8. In the second test case, the optimal subgraph is empty.
题意:一个有n个点m条边的图,每个点有相应的点权值,边有边权值。让你选择一些边,使得所选边权值总和减去所选边的端点的点权值总和的结果最大。
思路:
神奇网络流,将源点s向所有点连边,边权为点的权值,对于每条边,把它也看做一个点,并将它的两个端点与它连边,边权为无穷大,再将他与汇点t连边,边权为原来的边权。
设s、t为源点和汇点
对于边(id,u,v, w)id表示第几条边,u、v表示它的两个端点,w表示边权,weight[u]表示点u的权值
add(s,u,weight[u]),add(s,v,weight[v]),add(u,id+n,inf), add(v,id+n,inf), add(id+n,t,w)(id+n是为了避免点和边重合了)

对于一条边,如果它的边权大于他两个端点的点权之和,那么就要减去它的两个端点点权之和,反之则舍弃掉这条边。
所以答案就是所有边的边权之和减去最小割。
代码:
#include<bits/stdc++.h> #define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repp(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define perr(i,a,b) for(int i=a;i>b;i--)
#define pb push_back
#define eb push_back
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=;
ll max_3(ll a,ll b,ll c){if(a>b&&a>c)return a;if(b>c)return b;return c;}
ll min_3(ll a,ll b,ll c){if(a<b&&a<c)return a;if(b<c)return b;return c;}
ll gcd(ll a,ll b){return b==?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll qpow(ll a,ll n){ll r=;while(n){if(n&)r=(r*a)%mod;n>>=;a=(a*a)%mod;}return r;}
ll qmul(ll a,ll b){ll s=(long double)a/mod*b;s=a*b-s*mod;if(s<)s+=mod;if(s>=mod)s-=mod;return s;} template <typename _Tp> inline _Tp read(_Tp&x){
char c11=getchar(),ob=;x=;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=;
while(isdigit(c11))x=x*+c11-'',c11=getchar();if(ob)x=-x;return x;
}
int n,m; const int maxn=;
struct edge
{
ll v,cost,rev;//边的终点、边权、反向边
};
vector<edge>g[*maxn];//vector存图
ll deep[maxn];//表示源点到当前顶点的深度
ll iter[maxn];//当前弧,在其之前的边已经没有用了,避免了搜寻已经增广过的路径 void add(ll u,ll v,ll cost)//加边
{
g[u].pb((edge){v,cost,g[v].size()});
g[v].pb((edge){u,,g[u].size()-});
}
void bfs(int s)//建立分层网络,通过bfs计算从源点出发的距离标号
{
mst(deep,-);
queue<int>q;
deep[s]=;//源点深度为0
q.push(s);
while(!q.empty())
{
int v=q.front();q.pop();
for(int i=;i<g[v].size();i++)
{
edge &e=g[v][i];
if(e.cost>&&deep[e.v]==-)//如果还有容量能够到达i,并且i节点的深度未被标记
{
deep[e.v]=deep[v]+;
q.push(e.v);
}
}
}
}
ll dfs(ll v,ll t,ll f)//基于分层网络,通过dfs寻找增广路,x表示当前节点,f表示当前这条增广路径上的最小流量
{
if(v==t)return f;//找到汇点,返回
for(ll &i=iter[v];i<g[v].size();i++)
{
edge &e=g[v][i];
if(e.cost>&&deep[v]<deep[e.v])//找到能从v流通过去的相邻顶点
{
ll d=dfs(e.v,t,min(f,e.cost));
if(d>)
{
e.cost-=d;//更新残余网络
g[e.v][e.rev].cost+=d;//反向边
return d;
}
}
}
return ;//搜不到增广路径就返回0
}
ll dinic(ll s,ll t)//求s到t的最大流
{
ll flow=;
while()
{
bfs(s);
if(deep[t]<)return flow;//不存在分层网络,算法结束
mst(iter,);
ll f;
while((f=dfs(s,t,INF))>)
flow+=f;
}
} int main()
{
ll sum=;
read(n);read(m);
ll s=,t=+n+m,a;
rep(i,,n)
{
read(a);
add(s,i,a);
}
rep(i,,m)
{
ll u,v,w;
read(u);read(v);read(w);
add(u,i+n,LINF);
add(v,i+n,LINF);
add(i+n,t,w);
sum+=w;
}
printf("%lld\n",sum-dinic(s,t));
return ;
}
Petya and Graph/最大权闭合子图、最小割的更多相关文章
- codeforces 1082G - Petya and Graph 最大权闭合子图 网络流
题意: 让你选一些边,选边的前提是端点都被选了,求所有的边集中,边权和-点权和最大的一个. 题解: 对于每个边建一个点,然后就是裸的最大权闭合子图, 结果比赛的时候我的板子太丑,一直T,(不会当前弧优 ...
- CodeForces 1082 G Petya and Graph 最大权闭合子图。
题目传送门 题意:现在有一个图,选择一条边,会把边的2个顶点也选起来,最后会的到一个边的集合 和一个点的集合 , 求边的集合 - 点的集合最大是多少. 题解:裸的最大权闭合子图. 代码: #inclu ...
- 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)
https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- 【最大权闭合子图 最小割】bzoj1497: [NOI2006]最大获利
最大权闭合子图的模型:今天才发现dinic板子是一直挂的…… Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在 ...
- bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】
不要被5s时限和50000点数吓倒!大胆网络流!我一个5w级别的dinic只跑了1s+! 看起来没有最大权闭合子图的特征--限制,实际上还是有的. 我们需要把中转站看成负权点,把p看成点权,把客户看成 ...
- 洛谷 P2762 太空飞行计划问题 【最大权闭合子图+最小割】
--一道难在读入的题. 最后解决方案直接getline一行然后是把读优拆掉放进函数,虽然很丑但是过了. 然后就是裸的最大权闭合子图了,把仪器当成负权点向t连流量为其价格的边,s向实验连流量为实验报酬的 ...
- 【最大权闭合子图/最小割】BZOJ3438-小M的作物【待填】
[题目大意] 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植 ...
- POJ 2987 Firing【最大权闭合图-最小割】
题意:给出一个有向图,选择一个点,则要选择它的可以到达的所有节点.选择每个点有各自的利益或损失.求最大化的利益,以及此时选择人数的最小值. 算法:构造源点s汇点t,从s到每个正数点建边,容量为利益.每 ...
随机推荐
- 浅谈CSRF(Cross-site request forgery)跨站请求伪造
本文目录 CSRF是什么 CSRF攻击原理 CSRF攻击防范 CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack” ...
- docker时区不正确的问题修改记
前一阵子有一台服务器,mysql的时间比北京时间晚了8个小时.我知道是时区的问题,但是不知道为什么弄成这样,宿主机没有问题,后来一看mysql的docker,时区是错的. mybatis-plus打印 ...
- String常用处理方法
1.去空格 用于删除字符串的头尾空白符. 语法:public String trim() 返回值:删除头尾空白符的字符串. 删除所有空格 str.replace(" ", &quo ...
- Spring Data R2DBC响应式操作MySQL
1. 前言 在使用R2DBC操作MySQL数据库 一文中初步介绍了r2dbc-mysql的使用.由于借助DatabaseClient操作MySQL,过于初级和底层,不利于开发.今天就利用Spring ...
- 阿里云ecs轻量级服务器node镜像部署
这个是自带安装pm2,nginx,node,mongodb的环境的,目录在控制台有给出, server端的配置按照开发手册去操作即可. 而静态的页面.需要修改nginx的配置文件,找到nginx的ng ...
- 在Linux系统中使用Vim读写远程文件
大家好,我是良许. 今天我们讨论一个 Vim 使用技巧--用 Vim 读写远程文件.要实现这个目的,我们需要使用到一个叫 netrw.vim 的插件.从 Vim 7.x 开始,netrw.vim 就被 ...
- 没有学历如何从事Java开发?
学历成了当今社会一个衡量一个人能力的标准,未来只会越来越深入,也有的人说不要总是把学历挂嘴边,学历并不能代表能力,确实学历不能代表能力,但是学历是能代表一个的人学习深度,也是在职场上必备的一个敲门砖. ...
- PHP getdate() 函数
------------恢复内容开始------------ 实例 返回当前本地的日期/时间的日期/时间信息: <?phpprint_r(getdate());?> 运行实例 » 定义和用 ...
- ABC E - Active Infants 贪心 dp
LINK:Active Infants 一个快省选的人 还在写ABC(莫名觉得丢人 不过也无所谓了. 首先考虑 随便一个排列 我们考虑一下其是不是最优的 容易发现如果最大值没有在边界上的话我们直接把它 ...
- 使用ProxySQL实现MySQL Group Replication的故障转移、读写分离(二)
在上一篇文章<使用ProxySQL实现MySQL Group Replication的故障转移.读写分离(一) > 中,已经完成了MGR+ProxySQL集群的搭建,也测试了ProxySQ ...