P1073 [NOIP 2009 提高组] 最优贸易
链接
https://www.luogu.com.cn/problem/P1073
思路
刚开始的思路是tarjan:缩点,统计每个强联通分量的min和max。然后再根据有向图去求答案。但是这样太过于繁琐,所以采用分层图的办法。这篇题解讲的已经够详细了:https://www.luogu.com.cn/article/7h7adii9。但是代码重新搓了个,用的是链式前向星。注意这里的边卡了,改成1e6才行。
代码
#define _CRT_SECURE_NO_WARNINGS 0
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
using namespace std;
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int INF = LLONG_MIN;
int n, m;
int head[N * 3];
int cnt;
struct edge
{
int to, w, next;
}e[M * 3];
void init()
{
for (int i = 0; i < N * 3; i++)head[i] = -1;
for (int i = 0; i < M * 3; i++)e[i].next = -1;
cnt = 0;
return;
}
void addedge(int u, int v, int val)
{
e[cnt].to = v;
e[cnt].w = val;
e[cnt].next = head[u];
head[u] = cnt++;
}
int cal(int i, int num)
{
//i号节点第num层
return i + num * n;
}
int dis[N * 3];
bool inq[N * 3];
int spfa(int s)
{
memset(inq, 0, sizeof(inq));
for (int i = 1; i < N * 3; i++)
{
dis[i] = INF;
}
dis[s] = 0;
queue<int>q;
q.push(s);
inq[s] = true;
while (!q.empty())
{
int now = q.front();
q.pop();
inq[now] = false;
for (int i = head[now]; i != -1; i = e[i].next)
{
int v = e[i].to;
int w = e[i].w;
if (dis[now] + w > dis[v])
{
dis[v] = dis[now] + w;
if (!inq[v])
{
q.push(v);
inq[v] = true;
}
}
}
}
return 0;
}
signed main()
{
IOS;
init();
cin >> n >> m;
for (int i = 1, x; i <= n; i++)
{
cin >> x;
addedge(cal(i, 0), cal(i, 1), 0 - x);
addedge(cal(i, 1), cal(i, 2), x);
}
for (int i = 1; i <= m; i++)
{
int u, v, w;
cin >> u >> v >> w;
for (int ct = 0; ct <= 2; ct++)
{
addedge(cal(u, ct), cal(v, ct), 0);
if (w == 2)addedge(cal(v, ct), cal(u, ct), 0);
}
}
spfa(cal(1, 0));
cout << dis[cal(n, 2)];
return 0;
}

浙公网安备 33010602011771号