题意:有n+1个城市,从1~n号城市每个城市有一个评委要到0号城市和其他n-1个评委一起工作k天(这k天n个评委都要在),并且要把所有评委送回他原来所在的城市。现在有m个航班,只有从i号城市到0号城市,或者从0号城市到i号城市(航班到达的那天不能工作),问你最少需要花费多少钱。
思路:贪心维护dp1[i] 表示第i天所有评委到达的最小花费,dp2[i]表示第i天所有评委离开的花费. 处理完dp1,dp2后枚举一遍区间维护ans即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const ll INF = 0x3f3f3f3f3f3f3f3f-1;
struct node
{
ll d, u, v, c;
bool operator <(const node &a) const
{
return d < a.d;
}
}a[maxn];
ll vis[maxn], dp1[maxn], dp2[maxn];
int main(void)
{
int n, m, k;
while(cin >> n >> m >> k)
{
for(int i = 1; i <= m; i++)
scanf("%I64d%I64d%I64d%I64d", &a[i].d, &a[i].u, &a[i].v, &a[i].c);
for(int i = 0; i < maxn; i++)
vis[i] = -1, dp1[i] = INF;
sort(a+1, a+1+m);
ll num = 0, sum = 0;
for(int i = 1; i <= m; i++)
{
if(a[i].u == 0) continue;
if(vis[a[i].u] == -1)
num++, vis[a[i].u] = a[i].c, sum += a[i].c;
else
{
if(vis[a[i].u] > a[i].c)
{
sum -= vis[a[i].u];
vis[a[i].u] = a[i].c;
sum += a[i].c;
}
}
if(num == n)
dp1[a[i].d] = sum;
}
num = sum = 0;
for(int i = 0; i < maxn; i++)
vis[i] = -1, dp2[i] = INF;
for(int i = m; i >= 1; i--)
{
if(a[i].v == 0) continue;
if(vis[a[i].v] == -1)
num++, vis[a[i].v] = a[i].c, sum += a[i].c;
else
{
if(vis[a[i].v] > a[i].c)
{
sum -= vis[a[i].v];
vis[a[i].v] = a[i].c;
sum += a[i].c;
}
}
if(num == n)
dp2[a[i].d] = sum;
}
for(int i = 1; i < maxn; i++)
dp1[i] = min(dp1[i], dp1[i-1]);
for(int i = maxn-2; i >= 1; i--)
dp2[i] = min(dp2[i], dp2[i+1]);
ll ans = INF;
for(int i = 1; i+k+1 < maxn; i++)
ans = min(ans, dp1[i]+dp2[i+k+1]);
if(ans == INF) puts("-1");
else printf("%I64d\n", ans);
}
return 0;
}