HDU3251 Being a Hero——最大流最小割(Dinic+输出割边)⭐

本文介绍如何使用最大流算法解决一个特殊问题:在带权有向图中,通过割断某些边将选定的城市与其他城市隔离,以最大化点权和减去割边权的收益。文章详细阐述了计算过程,包括Dinic算法的应用、连通分量的划分以及确定割边的方法。
点这里

题意: 给定一个带权有向图,n个城市m条路(有边权),以及f个赠与你的城市(带有点权)。你需要从受赠与的城市中选择一些(可全部),并割断某些边将这些城市与其他城市隔开,你的最终受益等于所有受赠的点权和减去割掉的边权和。计算你的最大收益。并且输出割掉的边的编号。
题解: 要注意我们的收益是受赠与的城市的权值和减去割掉的边权和,而且必须要将你选择的城市与其他城市分割开。因此我们需要计算出能分割你的城市和其他的城市的最小边权和,而这个最小值,就是最大流的值。
  至于要打印割边的编号,那我们要清楚就算计算出了最大流,我们要舍弃哪些边。将你选择的城市看作一个连通分量T,将剩余的其他城市看作一割连通分量S,我们割的边,需要能连接这两个分量。


具体步骤:

  • 计算最大流: 这个只要用Dinic的模板就能计算,唯一要变通的就是设置一个超级汇点t = n + 1,将受赠的城市与超级汇点连接。
  • 分割: 利用Dinic中的残留容量图,对源点进行dfs,将所有残留容量不为零的边所连接的点,统统归入S的集合。如此一来,集合内的点即为连通分量S,而连接不到的点即为连通分量T。
  • 输出割边: 但是要注意!不是所有连接两个连通分量的边就一定是我们需要割的边。因为我们在图中加入了一个超级汇点t,所以我们还需要舍弃所以连接到超级汇点的边。

过程中犯的错:

  • init(): 我将超级汇点的设置放在了init函数中,而t = n + 1,必须在读入n之后才能进行初始化。
  • 割边需要舍弃连接超级汇点的边: 前面解释过原因。

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 10;
const int M = 2e5 + 10;

int T, n, m, f, k;
int s, t, cnt, sum;
int vis[N], cur[N], head[N], depth[N];
struct edge{
   
   	int v, w, next;} e[M];
void init(){
   
   	s = 1, t = n + 1, cnt = sum = 0;	for(int i = 0; i < N; i++)	vis[i] = 0, head[i] = -1;}
void add(int u, int v, int w){
   
   	e[cnt] = edge{
   
   v, w, head
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值