bzoj 3389

时间:2023-03-09 15:35:03
bzoj 3389

题意:给定1维连续T<= 1000000个点,以及n<=10000个线段,求最少的线段覆盖该区间。。

思路:很显然,贪心是可以做的。。不过这一题最有意思的是使可以转换为最短路模型。。

如果一条线段覆盖了[l, r],可以连l->r+1,距离为1的边。。

此外对于每个点i,连一条i->i-1,距离为0的边。。

那么实际上就是求1->n+1的最短路。。

感觉最短路模型还是很有意思的,跟2006北京赛区的最小割有点小像。。、

code:

 #include  <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int maxn = ;
struct edge{
int v, w, next;
} e[maxn << ];
int dis[maxn], last[maxn], n, m, tot;
int use[maxn]; inline void add(const int& u, const int& v, const int& w){
e[tot] = (edge){v, w, last[u]}; last[u] = tot++;
} void spfa(){
priority_queue<pii, vector<pii>, greater<pii> > q;
for (int i = ; i <= n + ; ++i) dis[i] = 0x3fffffff;
pii tmp;
memset(use, , sizeof(int) * (n + ));
q.push( make_pair(, ) ), dis[] = ;
int u, v;
while (!q.empty()){
u = q.top().second; q.pop();
if (use[u]) continue;
use[u] = ;
if (u == n+) return;
for (int p = last[u]; p != -; p = e[p].next){
v = e[p].v;
if (dis[u] + e[p].w < dis[v]){
dis[v] = dis[u] + e[p].w;
tmp.first = dis[v], tmp.second = v;
q.push(tmp);
}
}
}
} void solve(){
tot = ;
memset(last, -, sizeof(int) * (n + ));
int u, v;
for (int i = ; i < m; ++i){
scanf("%d%d", &u, &v);
add(u, v + , );
}
for (int i = ; i <= n; ++i)
add(i, i-, );
spfa();
// for (int i = 1; i <= n; ++i)
// printf("", dis[1]);
int ans = dis[n+];
if (ans == 0x3fffffff) puts("-1");
else cout << ans << endl;
} int main(){
// freopen("a.in", "r", stdin);
while (scanf("%d%d", &m, &n) != EOF){
solve();
}
}