題名
ポータルAcWing368
回答
あらゆる種類の関係を微分制約システムに変換し、各ノードの明るさの最小値を解き、それを最長パスの解法に変換します。
ddしましょうdはノードの明るさを表します。T = 1 T = 1T=1時間、d [A] -d [B]≥0、d [B] -d [A]≥0d[A] -d [B] \ geq 0、d [B] -d [A] \ geq 0d [ A ]−d [ B ]≥0 、d [ B ]−d [ A ]≥0;T = 2 T = 2T=2時間、d [B] -d [A]≥1d[B] -d [A] \ geq 1d [ B ]−d [ A ]≥1;T = 3 T = 3T=3時間、d [A] -d [B]≥0d[A] -d [B] \ geq 0d [ A ]−d [ B ]≥0;T = 4 T = 4T=4時間、d [A] -d [B]≥1d[A] -d [B] \ geq 1d [ A ]−d [ B ]≥1;T = 5 T = 5T=5時間、d [B] -d [A]≥0d[B] -d [A] \ geq 0d [ B ]−d [ A ]≥0。最も暗い明るさを確保するには111、d [0] = 0 d [0] = 0に設定d [ 0 ]=0、および制約∀A、d [A] − d [0]≥1\ forall A、d [A] -d [0] \ geq 1∀ A 、d [ A ]−d [ 0 ]≥1。
SPFA SPFA S P F A最長パスを解くO(NM)O(NM)O (N M )は実行が困難です。微分制約システムのエッジの重みが負でないことに注意してください。グラフにリングがある場合、リングのエッジの重みの合計は00でなければなりません。0 ;それ以外の場合、x> x x> xが表示されますバツ>>xこの種の解決できない状況。
タルジャンタルジャン T R jはAのn個解決するアルゴリズムSCC SCCをS C C、すべての強連結成分にゼロ以外の重みを持つエッジがあるかどうかを判断します。微分制約システムに解がある場合は、トポロジカル次数DPDPを使用します。D Pは、最長パスを解決します。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100005, maxm = 3 * 100005;
int N, M, fg, num, low[maxn], dfn[maxn];
int top, st[maxn], nr, rec[maxn];
int scc, sc[maxn], deg[maxn], dp[maxn];
int tot, head[maxn], to[maxm], nxt[maxm], cost[maxm];
int tot_c, hc[maxn], tc[maxm], nc[maxm], cc[maxm];
bool vs[maxn], in[maxn];
inline void add(int x, int y, int z) {
to[++tot] = y, cost[tot] = z, nxt[tot] = head[x], head[x] = tot; }
inline void add_c(int x, int y, int z) {
tc[++tot_c] = y, cc[tot_c] = z, nc[tot_c] = hc[x], hc[x] = tot_c; }
void dfs(int x)
{
vs[x] = 1;
for (int i = head[x]; i; i = nxt[i])
{
int y = to[i], z = cost[i];
if (sc[y] != scc)
continue;
if (z)
fg = 0;
else if (!vs[y])
dfs(y);
}
}
void tarjan(int x)
{
low[x] = dfn[x] = ++num;
st[++top] = x, in[x] = 1;
for (int i = head[x]; i; i = nxt[i])
{
int y = to[i];
if (!dfn[y])
{
tarjan(y);
low[x] = min(low[x], low[y]);
}
else if (in[y])
low[x] = min(low[x], dfn[y]);
}
if (low[x] == dfn[x])
{
++scc, nr = 0;
int y;
do
{
y = st[top--], in[y] = 0;
rec[++nr] = y, sc[y] = scc;
} while (y != x);
for (int i = 1; i <= nr; ++i)
vs[rec[i]] = 0;
dfs(x);
}
}
int main()
{
scanf("%d%d", &N, &M);
tot = tot_c = 1;
for (int i = 1, t, a, b; i <= M; ++i)
{
scanf("%d%d%d", &t, &a, &b);
if (t == 1)
add(b, a, 0), add(a, b, 0);
else if (t == 2)
add(a, b, 1);
else if (t == 3)
add(b, a, 0);
else if (t == 4)
add(b, a, 1);
else if (t == 5)
add(a, b, 0);
}
for (int i = 1; i <= N; ++i)
add(0, i, 1);
fg = 1;
for (int i = 0; i <= N; ++i)
if (!dfn[i])
tarjan(i);
if (!fg)
{
puts("-1");
return 0;
}
for (int i = 0; i <= N; ++i)
for (int j = head[i]; j; j = nxt[j])
{
int x = sc[i], y = sc[to[j]], z = cost[j];
if (x != y)
add_c(x, y, z), ++deg[y];
}
queue<int> q;
for (int i = 1; i <= scc; ++i)
if (!deg[i])
q.push(i);
while (q.size())
{
int x = q.front();
q.pop();
for (int i = hc[x]; i; i = nc[i])
{
int y = tc[i], z = cc[i];
dp[y] = max(dp[y], dp[x] + z);
if (!--deg[y])
q.push(y);
}
}
ll res = 0;
for (int i = 1; i <= N; ++i)
res += dp[sc[i]];
printf("%lld\n", res);
return 0;
}