codeforces 1307D Cow and Fields(最短路+思维)

题意:
一幅图,n个点,m条边。有k个特殊点,我们要任意选两个特殊点建边,起点为1,终点为n,求从起点到终点的最短路的最大值。
题解:
原图有一个最短路d,这是答案的上限,即 ans<=d.
最开始的想法就是0(n^2)暴力枚举,dis1[i]为起点到各点的最短路,dis2[i]为终点到各点的最短路,但很明显会超时,所以考虑当我们选择了两个点 i , j 建边并且强制走这条边时,最短路要么为dis1[i]+dis2[j]+1,要么为dis1[j]+dis2[i]+1,假如为1->i->j->n,那么满足dis1[i]+dis2[j]<dis1[j]+dis2[i],移项得dis1[i]-dis2[i]<dis1[j]-dis2[j],也就是说当dis1[i]-dis2[i]小的时候,那么会先到这个点,我们就可以根据这个排序k个点,既然要算dis1[i]+dis2[j]+1的最大值,我们就遍历一遍排序后的k个点,然后维护前缀dis1[i]最大值,当我们遍历到点 j 时,前【1,j-1】个点的dis1的最大值已经求出来了,那么直接与dis2[j]相加与ans比较更新最大值,最后还要和原图的最短路d比较取最小。
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
int dis1[MAXN];
int dis2[MAXN];
int vis[MAXN];
struct A
{
    
    
    int a;
    int val;
}f[MAXN];
bool cmp(A x,A y)
{
    
    
    return x.val<y.val;
}
struct Node
{
    
    
    int to;
    int next;
    int cost;
}e[MAXN<<1];
struct node
{
    
    
    int pos;
    ll val;
    friend bool operator<(node a,node b)
    {
    
    
        return a.val>b.val;
    }
};
int head[MAXN];
int cnt=0;
void add(int u,int v)
{
    
    
    e[cnt].to=v;
    e[cnt].next=head[u];
    e[cnt].cost=1;
    head[u]=cnt++;
}
void solve1(int s)
{
    
    
    memset(vis,0,sizeof vis);
    memset(dis1,0x3f3f3f,sizeof dis1);
    priority_queue<node> q;
    q.push(node{
    
    s,0});
    dis1[s]=0;
    while(!q.empty())
    {
    
    
        node now=q.top();
        q.pop();
        if(vis[now.pos]) continue;
        vis[now.pos]=1;
        for(int i=head[now.pos];i!=-1;i=e[i].next)
        {
    
    
            int v=e[i].to;
            if(dis1[v]>now.val+e[i].cost)
            {
    
    
                dis1[v]=now.val+e[i].cost;
                q.push(node{
    
    v,dis1[v]});
            }
        }
    }
}
void solve2(int s)
{
    
    
    memset(vis,0,sizeof vis);
    memset(dis2,0x3f3f3f,sizeof dis2);
    priority_queue<node> q;
    q.push(node{
    
    s,0});
    dis2[s]=0;
    while(!q.empty())
    {
    
    
        node now=q.top();
        q.pop();
        if(vis[now.pos]) continue;
        vis[now.pos]=1;
        for(int i=head[now.pos];i!=-1;i=e[i].next)
        {
    
    
            int v=e[i].to;
            if(dis2[v]>now.val+e[i].cost)
            {
    
    
                dis2[v]=now.val+e[i].cost;
                q.push(node{
    
    v,dis2[v]});
            }
        }
    }
}
int main()
{
    
    
    memset(head,-1,sizeof head);
    int n,m;
    int k;
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++)
    {
    
    
        cin>>f[i].a;
    }
    int u,v;
    for(int i=1;i<=m;i++)
    {
    
    
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    solve1(1);
    solve2(n);
    for(int i=1;i<=k;i++)
    {
    
    
        f[i].val=dis1[f[i].a]-dis2[f[i].a];
    }
    sort(f+1,f+1+k,cmp);
    int maxx=dis1[f[1].a];
    int ans=0;
    for(int i=2;i<=k;i++)
    {
    
    
        ans=max(ans,maxx+dis2[f[i].a]+1);
        maxx=max(maxx,dis1[f[i].a]);
    }
    ans=min(ans,dis1[n]);
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/107866598
今日推荐