Date:2022.01.22
题意:n个点m条边,起点为s终点为t,求最多连上多少条边能使s->t的距离不变近。
思路:好简单的2d。两次Dijkstra,分别以
s
s
s和
t
t
t为起点,距离分别为
d
i
s
t
1
[
]
、
d
i
s
t
2
[
]
dist1[]、dist2[]
dist1[]、dist2[]。之后
O
(
n
2
)
O(n^2)
O(n2)枚举任意两点,如果两点间有边则跳过;如果无边且加上这个边
<
i
,
j
>
<i,j>
<i,j>之后,如果
d
i
s
t
1
[
i
]
+
d
i
s
t
2
[
j
]
+
1
dist1[i]+dist2[j]+1
dist1[i]+dist2[j]+1
∣
∣
||
∣∣
d
i
s
t
1
[
j
]
+
d
i
s
t
2
[
i
]
+
1
dist1[j]+dist2[i]+1
dist1[j]+dist2[i]+1
<
<
<
d
i
s
t
1
[
t
]
dist1[t]
dist1[t],即若导致路径变短则不能选,否则能选。
除此之外,发现了个问题,堆优化Dijkstra里
p
r
i
o
r
i
t
y
q
u
e
u
e
priority_queue
priorityqueue中如果存
p
a
i
r
<
>
pair<>
pair<>类型且分别为点编号
j
j
j和到
j
j
j点的最短距离
d
i
s
t
[
j
]
dist[j]
dist[j],则
d
i
s
t
[
j
]
dist[j]
dist[j]要在前,
j
j
j要在后,才发现是因为
p
r
i
o
r
i
t
y
q
u
e
u
e
priority_queue
priorityqueue排序自动先按
p
a
i
r
<
>
pair<>
pair<>里的
f
i
r
s
t
first
first从小到大排序,再按
s
e
c
o
n
d
second
second 从小到大排序,放反了会错。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2010;
typedef long long LL;
typedef pair<LL, LL> PII;
LL dist1[N],dist2[N],n,m,ss,tt,g[N][N];
LL h1[N],e1[N],ne1[N],w1[N],idx1;
LL h2[N],e2[N],ne2[N],w2[N],idx2;
bool st1[N],st2[N];
void add1(LL x,LL y,LL c)
{
e1[idx1]=y;
ne1[idx1]=h1[x];
w1[idx1]=c;
h1[x]=idx1++;
}
void add2(LL x,LL y,LL c)
{
e2[idx2]=y;
ne2[idx2]=h2[x];
w2[idx2]=c;
h2[x]=idx2++;
}
void dijkstra1()
{
memset(dist1,0x3f,sizeof dist1);
dist1[ss]=0;
priority_queue<PII,vector<PII>,greater<PII> >heap;
heap.push({0,ss});
while(heap.size())
{
PII t=heap.top();heap.pop();
LL id=t.second,dis=t.first;
if(st1[id]) continue;
st1[id]=true;
for(int i=h1[id];i!=-1;i=ne1[i])
{
LL j=e1[i];
if(dist1[j]>dis+w1[i])
{
dist1[j]=dis+w1[i];
heap.push({dist1[j],j});
}
}
}
}
void dijkstra2()
{
memset(dist2,0x3f,sizeof dist2);
dist2[tt]=0;
priority_queue<PII,vector<PII>,greater<PII> >heap;
heap.push({0,tt});
while(heap.size())
{
PII t=heap.top();heap.pop();
LL id=t.second,dis=t.first;
if(st2[id]) continue;
st2[id]=true;
for(int i=h2[id];i!=-1;i=ne2[i])
{
LL j=e2[i];
if(dist2[j]>dis+w2[i])
{
dist2[j]=dis+w2[i];
heap.push({dist2[j],j});
}
}
}
}
int main()
{
memset(h1,-1,sizeof h1);
memset(h2,-1,sizeof h2);
cin>>n>>m>>ss>>tt;
while (m -- )
{
LL x,y;cin>>x>>y;
add1(x,y,1);add1(y,x,1);
add2(x,y,1);add2(y,x,1);
g[x][y]=g[y][x]=1;
}
dijkstra1();
dijkstra2();
LL ans=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(g[i][j]) continue;
if(1+dist1[i]+dist2[j]>=dist1[tt] && 1+dist1[j]+dist2[i]>=dist1[tt])
ans++;
}
cout<<ans;
return 0;
}