T1
题面:



第一题一开始没看到是最短路径,然后硬控了我一小时(呜呜呜,下次一定仔细审题)。
因为是最短路径,所以上来肯定直接跑 Dijkstra。那这时有一种非常水的情况:如果从起点到终点的最短路径小于等于 K,那任意两个点都可以连边,直接输出 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1)(但如果不判这种情况的话会 WA 一个点)。
另一种情况,就是最短路径比 K 大。这时我们就必须选两个点连起来,使得最短路径更短(当然,不一定是在最短路径上修改),我们假设从起点 s s s 走了 i i i 个单位长度,从终点 t t t 走了 j j j 个单位长度,那么要满足条件的话就要保证 i + j + L ≤ K i+j+L\le K i+j+L≤K,也就是 j ≤ K − L − i j\le K-L-i j≤K−L−i,那 j j j 能取的上限就是 K − L − i K-L-i K−L−i,因此在这个范围以内的我们都可以取,怎么算有多少个呢?很简单:排个序再二分一下不就对了。
代码:
#include<bits/stdc++.h>
#define int long long
#define code using
#define by namespace
#define plh std
#define INF 0x3f3f3f3f3f3f3f3f
code by plh;
int n,m,s,t,L,K,ans,dis1[200006],dis2[200006],vis[200006];
vector<pair<int,int>>v[200006];
void dijkstra(int st,int *dis)
{
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>pq;
for(int i=1;i<=n;i++)
{
dis[i]=INF;
vis[i]=0;
}
dis[st]=0;
pq.push(make_pair(dis[st],st));
while(!pq.empty())
{
pair<int,int>p=pq.top();
pq.pop();
int u=p.second;
if(vis[u])
{
continue;
}
vis[u]=1;
for(auto i:v[u])
{
if(dis[i.first]>dis[u]+i.second)
{
dis[i.first]=dis[u]+i.second;
pq.push(make_pair(dis[i.first],i.first));
}
}
}
}
signed main()
{
// freopen("portal.in","r",stdin);
// freopen("portal.out","w",stdout);
cin>>n>>m>>s>>t>>L>>K;
for(int i=1,x,y,z;i<=m;i++)
{
cin>>x>>y>>z;
v[x].push_back(make_pair(y,z));
v[y].push_back(make_pair(x,z));
}
dijkstra(s,dis1);
if(dis1[t]<=K)
{
cout<<n*(n-1)/2;
return 0;
}
dijkstra(t,dis2);
sort(dis1+1,dis1+1+n);
sort(dis2+1,dis2+1+n);
K-=L;
for(int i=1;i<=n;i++)
{
if(K<dis1[i])
{
break;
}
int cnt=upper_bound(dis2+1,dis2+n+1,K-dis1[i])-dis2-1;
ans+=cnt;
}
cout<<ans;
return 0;
}
T2
题面:



这题让我想到了这道题,只不过比那道题似乎还要好写一点。
首先看到后缀表达式,明显用栈建树,接下来就是要考虑反转表达式的值了。
首先,有两种无可奈何的情况(即必须把值改了):
- 1 ∣ x = 1 1\mid x=1 1∣x=

最低0.47元/天 解锁文章
466

被折叠的 条评论
为什么被折叠?



