| 点这里 |
|---|
题意: 给定一个带权有向图,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

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

被折叠的 条评论
为什么被折叠?



