玄学记录2-一个关于struct封装的东西定义的位置的问题 暨 P2766Solution

发布时间 2023-08-03 14:17:37作者: georegyucjr

后言

这是一道网络流的建模题
然后我这个板子是copy的
我把这个定义换了个位置结果就不一样

嗯 是这样的!
然后这篇东西会很杂 思路会比较简洁 因为把建边给讲清楚了就是模板了

题目

Problem : problem on luogu

思路

现在我们要解决两个问题

  1. 最长不下降子序列

    我们将所有转移的(从\(u\)\(v\) 进行类似于网络流的建边)

  2. 有些值只能算一次

    这个套路比较常见,就是拆点。我们把一个点拆成两个,一个是\(i\),另一个是\(i + n\)。对一个点对\((i, i^{'})\),我们将\(i\)当作将边联入的点,\(i^{'}\)作为把边联出的点。如果我们要控制这个点出现过一次,那就在\(i\)\(i^{'}\)之间连一条为\(1\)的边,否则连一条\(flow = \infty\)的边,我代码连的是n,因为现在不会走过到n次。

代码

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

const int V = 20100;
const int E = 1001000;
template<typename T>
struct FlowGraph {
	int s, t, vtot;
	int head[V], etot;
	int dis[V], cur[V];
	struct edge {
		int v, nxt;
		T f;
	} e[E * 2];
	void addedge(int u,int v, T f){
		e[etot]= {v, head[u], f}; head[u] = etot++;
		e[etot]= {u, head[v], 0}; head[v] = etot++;
	}

	bool bfs() {
		for (int i = 1; i <= vtot; i++) {
			dis[i] = 0;
			cur[i] = head[i];
		}
		queue<int> q;
		q.push(s); dis[s] = 1;
		while (!q.empty()) {
			int u = q.front(); q.pop();
			for (int i = head[u]; ~i; i = e[i].nxt) {
				if (e[i].f && !dis[e[i].v]) {
					int v = e[i].v;
					dis[v] = dis[u] + 1;
					if (v == t) return true;
					q.push(v);
				}
			}
		}
		return false;
	}

	T dfs(int u, T m) {
		if (u == t) return m;
		T flow = 0;
		for (int i = cur[u]; ~i; cur[u] = i = e[i].nxt)
			if (e[i].f && dis[e[i].v] == dis[u] + 1) {
				T f = dfs(e[i].v, min(m, e[i].f));
				e[i].f -= f;
				e[i ^ 1].f += f;
				m -= f;
				flow += f;
				if (!m) break;
			}
		if (!flow) dis[u] = -1;
		return flow;
	}
	T dinic(){
		T flow=0;
		while (bfs()) flow += dfs(s, numeric_limits<T>::max());
		return flow;
	}
	void init(int s_, int t_, int vtot_) {
		s = s_;
		t = t_;
		vtot = vtot_;
		etot = 0;
		for (int i = 1; i <= vtot; i++) head[i] = -1;
	}
};

const int N = 510;
FlowGraph<int> g;
int n, a[N], f[N];
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		f[i] = 1;
		for (int j = 1; j < i; j++) if (a[i] >= a[j])
			f[i] = max(f[i], f[j] + 1);
		ans = max(ans, f[i]);
	}
	printf("%d\n" ,ans);
	int s = 2 * n + 1, t = 2 * n + 2;
	g.init(s, t, t);
	for (int i = 1; i <= n; i++) {
		if (f[i] == 1) g.addedge(s, i, n);
		if (f[i] == ans) g.addedge(i + n, t, n);
		g.addedge(i, i + n, 1);
	}
	for (int i = 1; i <= n; i++) 
		for (int j = i + 1; j <= n; j++)
			if (a[i] <= a[j] && f[j] == f[i] + 1)
				g.addedge(i + n, j, 1);
	printf("%d\n", g.dinic());
	g.init(s, t, t);
	for (int i = 1; i <= n; i++) {
		if (f[i] == 1) g.addedge(s, i, n);
		if (f[i] == ans) g.addedge(i + n, t, n);
		if ((i != 1 && i != n) || ans == 1) g.addedge(i, i + n, 1);
		else g.addedge(i, i + n, n);
	}
	for (int i = 1; i <= n; i++) 
		for (int j = i + 1; j <= n; j++)
			if (a[i] <= a[j] && f[j] == f[i] + 1)
				g.addedge(i + n, j, 1);
	printf("%d\n", g.dinic());

}

然后我在本地将

FlowGraph<int> g;

换到了main()里面,然后就圆寂了,跑出了问未定义行为的提示(别问我怎么弄到的)。

前言

如果有大佬知道为什么吧这个东西放到main里面就会挂的会,请指点一下!我是\(Mn Zn\),很需要大佬们的帮助!!!!!!!!!