LG-P3872 [TJOI2010] Movie fans

Portal: P3872 [TJOI2010] Movie Fan

Based on the maximum weight closed subgraph, plus a little extension.

The solution to this problem is mainly to talk about the maximum weight closed subgraph in detail

maximum weight closed subgraph

1. Concept

  • Closed subgraph: in the original image GGIn a closed subgraph of G , for each node, it is in GGAll nodes reachable in G are included in this subgraph.

  • Maximum weight closed subgraph: the original image GGA closed subgraph with the largest sum of weights in G.

2. Use

Goal: Find the maximum weight closed subgraph of a graph.

<1>

First create a super source and super sink.

For each weighted node:

  • If the node is positive, it is connected to the super source point, and the flow is the weight of this point;
  • On the contrary, it is connected to the super sink, and the flow is the opposite of the weight of the point.

Obviously, without considering "every point in GGWhen all nodes that can be reached in G are included in this subgraph", the maximum weight "closed subgraph" must be the sum of all positive weights, that is, the sum of all edge flows now connected to the source point .

At this point, the reason for the above-mentioned edge building method is clear: to distinguish points with positive and negative weights.

<2>

Then add constraints and create edges between points.

At this point, it can be vaguely found that we will use the minimum cut to find the maximum weight subgraph.

Cut some edges so that the source point and sink point are not connected, and the subgraph where the source point is located is the maximum weight closed subgraph of the original graph.

Looking back: what is the flow of these edges?

The flow of these edges is inf infi n f . Because "each point is inGGAll nodes that can be reached in G are included in this subgraph", so make sure that these edges will not be cut off.

<3>

At this point, it can be found that the cut edges are all edges connected to the source or sink.

  • If the edge connecting a node with negative weight to a sink is cut:

    It means that it is the optimal state in the maximum-weight closed subgraph at this time, but the weight of the maximum-weight closed subgraph must be subtracted from the absolute value of the weight of this point.

  • If the edge connecting a positive weight node to a sink is cut:

    It means that it is the optimal state that it is not placed in the maximum-weight closed subgraph at this time, but the weight of the maximum-weight closed subgraph must be subtracted from the weight of this point.

In this way, the sum of the weights of the maximum weight closed subgraph is: the sum of the positive weights - the minimum cut.

Then the minimum cut can be converted into a maximum flow to solve.

return to this topic

It can be seen that in the maximum weight closed subgraph template, the edges in the original graph cannot be deleted, but this question can be deleted.

Just deleting this edge also requires a cost, so set the traffic of this edge as the cost instead of inf infi n f is enough.

The rest is the template of the maximum weight closed subgraph.

AC Code

#include<bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define inf 10000000
#define maxn 700
#define maxm 1000005

int n, m;
int sa[maxn];
int cnt = 1, hd[maxn];
struct node{
    
    
	int to, nxt;
	int flw;
}e[maxm];
int in[maxn];
vector <int> out[maxn];
int dep[maxn], vis[maxn];
int sum, ans;
int s, t;

inline int id(int i, int j)
{
    
    
	return (i - 1) * m + j;
}

inline void add(int u, int v, int f)
{
    
    
	e[++cnt] = (node){
    
    v, hd[u], f};
	hd[u] = cnt;
	e[++cnt] = (node){
    
    u, hd[v], 0};
	hd[v] = cnt;
}

inline void topo()
{
    
    
	queue <int> q;
	rep(i, 1, n * m)
	{
    
    
		if(!in[i])
			vis[i] = 1, q.push(i);
	}
	while(!q.empty())
	{
    
    
		int u = q.front();
		q.pop();
		for(int i = 0; i < out[u].size(); ++i)
		{
    
    	
			int v = out[u][i];
			in[v] -= 1;
			if(!vis[v] and !in[v])
				vis[v] = 1, q.push(v);
		}
	}
}

inline bool bfs()
{
    
    
	queue <int> q;
	memset(dep, 0, sizeof dep);
	dep[s] = 1, q.push(s);
	while(!q.empty())
	{
    
    
		int u = q.front();
		q.pop();
		for(int i = hd[u], v; i; i = e[i].nxt)
		{
    
    
			if(!dep[v = e[i].to] and e[i].flw)
				dep[v] = dep[u] + 1, 
				q.push(v);
		}
	}
	return dep[t] ? 1 : 0;
}

inline int dfs(int u, int cm)
{
    
    
	if(u == t or !cm) return cm;
	int lv = 0;
	for(int i = hd[u], v; i and cm; i = e[i].nxt)
	{
    
    
		if(!e[i].flw) continue;
		if(dep[v = e[i].to] != dep[u] + 1) continue;
		int res = dfs(v, min(cm, e[i].flw));
		e[i].flw -= res; 
		e[i ^ 1].flw += res;
		cm -= res, lv += res;
	}
	if(!lv) dep[u] = 0;
	return lv;
}

inline int dinic()
{
    
    
	while(bfs())
		ans += dfs(s, inf);
	return ans;
}

signed main()
{
    
    
	scanf("%d%d", &n, &m);
	s = n + 1, t = s + 1;
	rep(i, 1, n) 
	{
    
    
		scanf("%d", &sa[i]);
		if(sa[i] < 0) add(i, t, -sa[i]);
		else add(s, i, sa[i]), sum += sa[i];
	}
	rep(i, 1, m)
	{
    
    
		int ut, vt, dt;
		scanf("%d%d%d", &ut, &vt, &dt);
		add(ut, vt, dt);
	}
	printf("%d\n", sum - dinic());
	return 0;
}

Thanks for reading.

It is hard for the administrator to review, if there is any problem, please point out.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324116481&siteId=291194637