[CF1483D]Useful Edges
Posted Tan_tan_tann
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1483D]Useful Edges相关的知识,希望对你有一定的参考价值。
Useful Edges
题解
首先我们考虑如何判断一条边合法,我们定义
u
,
v
u,v
u,v之间的最短路为
d
i
s
u
,
v
dis_{u,v}
disu,v,询问三元组的长度为
a
s
k
u
,
v
ask_{u,v}
asku,v,记边为
(
x
,
y
)
(x,y)
(x,y),询问为
(
u
,
v
)
(u,v)
(u,v)
那么对于边
i
i
i,条件是
∃
j
,
d
i
s
u
j
,
x
i
+
p
a
i
d
x
i
,
y
i
+
d
i
s
y
i
,
v
j
⩽
a
s
k
u
j
,
v
j
\\exists j,dis_{u_{j},x_{i}}+paid_{x_{i},y_{i}}+dis_{y_{i},v_{j}}\\leqslant ask_{u_{j},v_{j}}
∃j,disuj,xi+paidxi,yi+disyi,vj⩽askuj,vj
考虑移项,可得
∃
j
,
d
i
s
u
j
,
x
i
+
p
a
i
d
x
i
,
y
i
⩽
a
s
k
u
j
,
v
j
−
d
i
s
y
i
,
v
j
\\exists j,dis_{u_{j},x_{i}}+paid_{x_{i},y_{i}}\\leqslant ask_{u_{j},v_{j}}-dis_{y_{i},v_{j}}
∃j,disuj,xi+paidxi,yi⩽askuj,vj−disyi,vj
我们可以枚举
u
u
u和
y
y
y,这样前面半截就只与
x
x
x相关,后面半截就只与
v
v
v相关。
那么,对于每个
(
u
,
y
)
(u,y)
(u,y),由于是存在,我们可以找到最大的
a
s
k
u
,
v
−
d
i
s
y
,
v
ask_{u,v}-dis_{y,v}
asku,v−disy,v,此后再枚举
x
x
x,如果有
d
i
s
u
,
x
+
p
a
i
d
x
,
y
⩽
(
a
s
k
u
,
v
−
d
i
s
y
,
v
)
max
dis_{u,x}+paid_{x,y}\\leqslant (ask_{u,v}-dis_{y,v})_{\\max}
disu,x+paidx,y⩽(asku,v−disy,v)max,则该边
(
x
,
y
)
(x,y)
(x,y)就是合法的。
我们只需要枚举
(
u
,
y
)
(u,y)
(u,y),算出该数对使得那些
x
x
x合法,最后统计合法的边数即可。
至于
d
i
s
dis
dis数组,可以先通过Floyed求出来。
时间复杂度 O ( n 3 ) O\\left(n^3\\right) O(n3)
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define mp make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const LL mo=1e9+7;
const LL inv2=5e8+4;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int n,m,q,paid[605][605],dis[605][605],ask[605][605],ans;bool vis[605][605];
struct edge{int u,v;}e[MAXN];
signed main(){
read(n);read(m);memset(paid,0x3f,sizeof(paid));
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=m;i++){
int u,v,w;read(u);read(v);read(w);e[i]=(edge){u,v};
dis[u][v]=dis[v][u]=paid[u][v]=paid[v][u]=w;
}
for(int i=1;i<=n;i++)paid[i][i]=dis[i][i]=0;
for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
if(i!=j&&i!=k&&j!=k)dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
//for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)printf("dis%d %d:%d\\n",i,j,dis[i][j]);
read(q);
for(int i=1,u,v,w;i<=q;i++)read(u),read(v),read(w),ask[u][v]=ask[v][u]=w;
for(int u=1;u<=n;u++)
for(int y=1;y<=n;y++){
int maxx=0;for(int v=1;v<=n;v++)maxx=max(maxx,ask[u][v]-dis[y][v]);
for(int xCF981C Useful Decomposition 树 dfs 二十三 *
[TIA PORTAL][CONVERT] Convert Char Array to DInt...DInt to Char Array..Useful and easy function(代码片段
CF981C Useful Decomposition树/思维