Abstract
Idea
显然是一个差分约束系统。不妨用 dist[i] 表示前 i 个位置种的树的数目,那么,容易得出下列方程:
- dist[i] >= dist[i-1]
- dist[i] - dist[i-1] <= 1 (每个位置至多能种一颗树)
题目要求 b 到 e 之间至少种 t 棵树,其数学形式就是:
- dist[b] - dist[e-1] >= t
依据上面三种方程,我们构建了一个完整的差分约束系统,接下来跑最短路求出 dist 数组的一个可能取值就行了。然后,考虑到边界条件 dist[0] = 0,所以答案是 dist[n] - dist[0] 。
Code
#include <bits/stdc++.h>
using namespace std;
int n, h;
namespace graph
{
const int maxn = 100000;
int head[maxn];
int cnt;
struct Edge
{
int next, to, value;
} edge[maxn];
void add(int u, int v, int c)
{
edge[++cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].value = c;
head[u] = cnt;
return;
}
};
bool SPFA(int start, int dist[])
{
queue<int> q;
bool inQueue[graph::maxn] = {false};
int count[graph::maxn] = {0};
for (int i = 1; i < n + 1; i++)
{
dist[i] = 0x3f3f3f3f;
}
dist[start] = 0;
q.push(start);
inQueue[start] = true;
count[start] = 1;
while (!q.empty())
{
int u = q.front();
q.pop();
inQueue[u] = false;
for (int i = graph::head[u]; i; i = graph::edge[i].next)
{
int v = graph::edge[i].to;
int w = graph::edge[i].value;
if (dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
if (!inQueue[v])
{
q.push(v);
inQueue[v] = true;
count[v]++;
}
if (count[v] > n + 1)
{
return true;
}
}
}
}
return false;
}
void solve()
{
cin >> n >> h;
for (int i = 0; i < h; i++)
{
int e, b, t;
cin >> b >> e >> t;
graph::add(e, b - 1, -t);
}
for (int i = 0; i < n; i++)
{
graph::add(i, i + 1, 1);
graph::add(i + 1, i, 0);
}
for (int i = 0; i < n + 1; i++)
{
graph::add(n + 1, i, 0);
}
int dist[graph::maxn];
SPFA(n + 1, dist);
cout << dist[n] - dist[0];
return;
}
signed main()
{
int t = 1;
while (t--)
{
solve();
}
return 0;
}
标签:洛谷,P1250,int,graph,++,edge,种树,dist,maxn
From: https://www.cnblogs.com/carboxylBase/p/18357800