problem
You are given n closed, integer intervals [ai, bi] and n integers c1, …, cn.
Write a program that:
reads the number of intervals, their endpoints and integers c1, …, cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i = 1, 2, …, n,
writes the answer to the standard output
在 [ai,bi] [ a i , b i ] 至少有 ci c i 个相同的数,求满足条件的最小集合大小
题解
求最小值,即对约束图求最长路,对于线性约束条件:
dj−di≥x
d
j
−
d
i
≥
x
,则添加边
(i,j)
(
i
,
j
)
且
w(i,j)=x
w
(
i
,
j
)
=
x
题意中的条件为:
d[bi]−d[ai−1]≥ci
d
[
b
i
]
−
d
[
a
i
−
1
]
≥
c
i
即加边
(ai−1,bi)
(
a
i
−
1
,
b
i
)
且
w(ai−1,bi)=ci
w
(
a
i
−
1
,
b
i
)
=
c
i
题中有隐藏条件:
0≤d[i+1]−d[i]≤1
0
≤
d
[
i
+
1
]
−
d
[
i
]
≤
1
0≤d[i+1]−d[i]
0
≤
d
[
i
+
1
]
−
d
[
i
]
即加边
(i,i+1)
(
i
,
i
+
1
)
且
w(i,i+1)=0
w
(
i
,
i
+
1
)
=
0
d[i+1]−d[i]≤1
d
[
i
+
1
]
−
d
[
i
]
≤
1
进行等价变换,得
d[i]−d[i+1]≥−1
d
[
i
]
−
d
[
i
+
1
]
≥
−
1
即加边
(i+1,i)
(
i
+
1
,
i
)
且
w(i+1,i)=−1
w
(
i
+
1
,
i
)
=
−
1
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+100;
struct node
{
int to,w;
node (int n1,int n2)
{
to = n1;
w = n2;
}
};
vector <node> v[maxn];
int n,le,ri,l,r,c;
int d[maxn];
bool vis[maxn];
void spfa()
{
for (int i=le;i<=ri;i++)
{
d[i] = -maxn;
vis[i] = 0;
}
queue <int> Q;
Q.push(le);
vis[le] = 1;
d[le] = 0;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = false;
for (int i=0;i<v[u].size();i++)
{
int t = v[u][i].to;
int dt = v[u][i].w;
if (d[t] < d[u]+dt)
{
d[t] = d[u]+dt;
if (!vis[t])
{
vis[t] = true;
Q.push(t);
}
}
}
}
return;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
for (int i=0;i<maxn;i++) v[i].clear();
ri = 0,le = maxn;
for (int i=0;i<n;i++)
{
scanf("%d %d %d",&l,&r,&c);
l++,r++;
le = min(l,le);
ri = max(r,ri);
v[l-1].push_back(node(r,c));
}
le--;
for (int i=le;i<ri;i++)
{
v[i].push_back(node(i+1,0));
v[i+1].push_back(node(i,-1));
}
spfa();
printf("%d\n",d[ri]);
}
return 0;
}