绵阳东辰国际test201909.29

爆零场!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

说说我的心路历程:

n个点,m条双向边---->缩点?

颜色只有三种,最大值-------->dp?

然后就搞来搞去就没搞出来

solution:

预处理每个点在每种颜色下处于那个联通块

对每种颜色分别建图Tarjan缩点

假如询问点为x,此时的颜色为t

则在此时颜色t的图中可以走到的(也就是它所处的强连通分量),就都可走(过程又不用花费)

考虑要变颜色的路径可能会与以前的颜色路径重复,怎么办?容斥减掉就好

这里就可以用map维护

最后分情况对于每个点取个最大的就好

code by chitongzi

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100000 + 5, M = 200000 + 5;
inline void read(int&a)
{
	a = 0; char k = getchar (); int f = 1;
	while (k > '9' || k < '0') { if (k == '-') f = -1; k = getchar (); }
	while (k >= '0' && k <= '9') { a = a * 10 + k - '0'; k = getchar (); }
	a *= f;
}
int c[N];
struct Graph {
	int fr[M << 1], to[M << 1], h[N], tot;
	int stk[N], top, dfn[N], low[N], dftot, color[N], cocnt, ans[N];
	int sumc[N];
	bool ins[N];
	inline void adde (int u, int v)
	{
		tot++;
		fr[tot] = h[u];
		to[tot] = v;
		h[u] = tot;
	}
	inline void tarjan (int p)
	{
		dfn[p] = ++dftot;
		ins[p] = 1;
		stk[++top] = p;
		low[p] = dfn[p];
		for (int i = h[p]; i; i = fr[i])
		{
			if (!dfn[ to[i] ])
			{
				tarjan ( to[i] );
				low[p] = min (low[p], low[ to[i] ]);
			}
			else if (ins[ to[i] ])
				low[p] = min (low[p], dfn[ to[i] ]);
		}
		if (low[p] == dfn[p])
		{
			bool flag = true;
			++cocnt;
			while (flag)
			{
				if (stk[top] == p) flag = false;
				color[ stk[top] ] = cocnt;
				sumc[cocnt] += c[ stk[top] ];
				ins[ stk[top] ] = 0;
				--top;
			}
		}
	}
}g[4];
map<pair<int, int>, int> mp[3];
int n, m;
signed main ()
{
	freopen ("grape.in", "r", stdin);
	freopen ("grape.out", "w", stdout);
	read(n), read(m);
	for (int i = 1; i <= n; ++i)read (c[i]);
	for (int i = 1, x, y, z; i <= m; ++i)
	{
		read (x), read (y), read (z);
		for (int k = 1; k <= 3; ++k)
			if (k != z)
				g[k].adde (x, y), g[k].adde (y, x);
	}
	for (int k = 1; k <= 3; ++k)
		for (int i = 1; i <= n; ++i)
			if (!g[k].dfn[i])
				g[k].tarjan (i);
	for (int i=1; i <= n; ++i)
	{
		int idx = g[1].color[i], idy = g[2].color[i], idz = g[3].color[i];
		mp[0][ make_pair (idx, idy) ] += c[i];
		mp[1][ make_pair (idy, idz) ] += c[i];
		mp[2][ make_pair (idx, idz) ] += c[i];
	}
	for (int i = 1; i <= n; ++i)
	{
		int idx = g[1].color[i], idy = g[2].color[i], idz = g[3].color[i];
		g[1].ans[idx]=max(g[1].ans[idx],g[1].sumc[idx]+g[2].sumc[idy]-mp[0][make_pair(idx,idy)]);
		g[1].ans[idx]=max(g[1].ans[idx],g[1].sumc[idx]+g[3].sumc[idz]-mp[2][make_pair(idx,idz)]);
		g[2].ans[idy]=max(g[2].ans[idy],g[2].sumc[idy]+g[1].sumc[idx]-mp[0][make_pair(idx,idy)]);
		g[2].ans[idy]=max(g[2].ans[idy],g[2].sumc[idy]+g[3].sumc[idz]-mp[1][make_pair(idy,idz)]);
		g[3].ans[idz]=max(g[3].ans[idz],g[3].sumc[idz]+g[1].sumc[idx]-mp[2][make_pair(idx,idz)]);
		g[3].ans[idz]=max(g[3].ans[idz],g[3].sumc[idz]+g[2].sumc[idy]-mp[1][make_pair(idy,idz)]);
	}
	int q;
	read (q);
	for (int i = 1; i <= q; ++i)
	{
		int tmp; read (tmp);
		int idx = g[1].color[tmp], idy = g[2].color[tmp], idz = g[3].color[tmp];
		printf ("%lld
", max (g[1].ans[ idx ], max (g[2].ans[ idy ], g[3].ans[ idz ])));
	}
	return 0;
}

原文地址:https://www.cnblogs.com/wzxbeliever/p/11608359.html