【题解】Vijos1404 遭遇战(最短路图论套路)

【题解】Vijos1404 遭遇战(最短路图论套路)

感觉一定要有建模的思想,不管什么东西要抽象建模之后再用算法解决...

求最短代价就可能可以用最短路,这句话不是强行解释,而是因为图论建模过后,可能存在很多不合法的情况,但是由于我们只是求最短路,所以我们只要保证对于每一条最短路可以构造一个与之对应的合法原问题解

给你一条数轴和 m 条线段,第 i 条线段覆盖区间 [Li,Ri] ,选择它需要代价 Ci 。
请选出代价和最小的一组线段使得区间 [L,R] 中的每一段都被覆盖。

考虑建立这些有向边:\((L_i,R_i+1,C_i),(x,x-1,0)\)

考虑对于一个最短路,构造方案就是这条最短路经过的所有\(i\)选上即可。

充分性和必要性都挺显然的,因为(不绕环的)路径和原问题的解可以一一对应,而一定存在一条最短路使得整条最短路没有环。

加1的原因是我们只要整点覆盖

//@winlere
#include
#include
#include
#include
#include
#include

using namespace std;  typedef long long ll;   char __buf[1<<18],*__c=__buf,*__ed=__buf;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(!isdigit(c))f|=c==45,c=getchar();
      while(isdigit(c)) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const int maxn=9e4+5;
const int inf=0x3f3f3f3f;
int d[maxn];
struct E{int to,w;};
vector e[maxn];
typedef pair P;
priority_queue,greater

> q; inline void add(const int&fr,const int&to,const int&w){e[fr].push_back({to,w});} int n,L,R; inline void dij(){ memset(d,0x3f,sizeof d); q.push({d[L]=0,L}); while(q.size()){ auto g=q.top(); q.pop(); if(g.first>d[g.second]) continue; for(auto t:e[g.second]) if(d[t.to]>g.first+t.w) q.push({d[t.to]=g.first+t.w,t.to}); } } int main(){ n=qr(); L=qr(); R=qr(); for(int t=1,t1,t2,v;t<=n;++t){ t1=max(L,qr()),t2=min(qr()+1,R+1); add(t1,t2,v=qr()); add(t2,t1,v); } for(int t=L+1;t<=R+1;++t) add(t,t-1,0); dij(); if(d[R+1]!=d[0]) printf("%d\n",d[R+1]); else puts("-1"); return 0; }

你可能感兴趣的:(【题解】Vijos1404 遭遇战(最短路图论套路))