绵阳东辰国际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\n", max (g[1].ans[ idx ], max (g[2].ans[ idy ], g[3].ans[ idz ])));
}
return 0;
}