T2
(个人觉得比
T
1
T1
T1好理解一些,也可能是我
c
f
cf
cf打少了吧
q
w
q
qwq
qwq)
Solution
\text{Solution}
Solution
一道将区间问题转换成图论的题。
设
0
0
0区间分别是
[
l
,
r
]
,
[
L
,
R
]
[l,r],[L,R]
[l,r],[L,R],那么要使
0
0
0区间全变成
1
1
1区间只能有这几种覆盖方法:
[
l
,
r
]
&
[
L
,
R
]
[
l
,
L
]
&
[
r
,
R
]
[
l
,
R
]
&
[
r
,
L
]
[l,r]\&[L,R]\ [l,L]\&[r,R]\ [l,R]\&[r,L]
[l,r]&[L,R] [l,L]&[r,R] [l,R]&[r,L] 。题目说要考虑求最小代价 那容易想到啥? 最短路!
那么就在读入时将区间的左右端点连边,边上权值就是区间修改代价,对这几种情况分别跑一次最短路并更新
a
n
s
ans
ans,最后检验可否修改并输出答案即可。
当时还想了想关于区间覆盖奇偶次数这个问题,然后菜逼发现这样很难既判定次数又考虑最小代价,发现如果要使区间全部变成
1
1
1并且代价最小,那么只有那几种覆盖可能。合法的情况也一定是最短路可以跑出来的,如果跑不出来那必定覆盖区间与
0
0
0区间不能完全重合,输出
−
1
-1
−1即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=(int)5e5+50;
priority_queue<pair<int,int> >q;
int a,b,c,d,e,m;
int tot,fir[N<<1],to[N<<1],nxt[N<<1],w[N<<1];
int dis[N];
bool v[N];
inline void add(int x,int y,int z){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;w[tot]=z;}
inline int dij(int st,int ed){
memset(dis,0x3f,sizeof(dis));memset(v,0,sizeof(v));
dis[st]=0,q.push(make_pair(0,st));
while(!q.empty()){
int x=q.top().second;q.pop();
if(v[x]) continue; v[x]=1;
for(int i=fir[x];i;i=nxt[i]){
int y=to[i],z=w[i];
if(dis[y]>dis[x]+z) dis[y]=dis[x]+z;q.push(make_pair(-dis[y],y));
}
}
return dis[ed];
}
inline int read(){
int cnt=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
while(isdigit(c)){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}
return cnt*f;
}
signed main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
a=read(),b=read(),c=read(),d=read(),e=read();m=read();
int l,r,L,R;
for(int i=1;i<=m;++i) l=read(),r=read(),add(l,r+1,r-l+1),add(r+1,l,r-l+1);
l=a+1,r=a+b+1;L=a+b+c+1,R=a+b+c+d+1;
int ans=1e18;
ans=min(ans,dij(l,r)+dij(L,R));
ans=min(ans,dij(l,L)+dij(r,R));
ans=min(ans,dij(l,R)+dij(r,L));
if(ans==1e18) cout<<"-1";
else cout<<ans;
return 0;
}