D - Cow and Fields

题意 给出n个点,m条边,还有k个特殊点;

求从1到n的最短路,但又不是单纯求最短;

我们需要在这k个特殊点中选择两个点,将这两个点相连,再去求路径最长的最短路

那么 ,我们可以先跑两边spfa求出从顶点1开始的最短路和从n开始的最短路,分别为disa disb;

然后,我们再将特殊点根据disa[x]-disb[x]<disa[y]-disb[y],来排序;

为啥这样排呢,因为  disa[x]+1+disn[y]<disa[y]+1+disn[x],  移项之后便是上面的式子;

为什么是这样的式子呢,首先我们就要确定排序的宗旨,就是让路径是从1到x,从x到y,再从y到n;

而不是从1到y,从y到x,再从x到n 这样子就绕了个圈;我们也不好判断;

所以我们将特殊点处理为不用“绕圈子"的样子,这样我们就可以O(n)的复杂度来遍历;

因此,要让答案最大,我们就在每次更新完ans之后,再更新一下特殊点的左端点(根据距点1的距离更远更优来选择)

这样子代码基本就完成;

但是有一个细节;

就是可能特殊点对最短路没有贡献,意思就是,即使连接了这两个特殊点,得出的答案依旧为inf

所以我们最后得ans=min(ans,disa[n]);

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 const int inf=0x3f3f3f3f;
 5 int a[maxn];
 6 struct node
 7 {
 8     int v,nxt,w;
 9 }G[maxn<<1]; int head[maxn]; int num;
10 int disa[maxn];
11 int disb[maxn];
12 int dis[maxn];
13 int vis[maxn];
14 int n,m,k;
15 void add(int u,int v)
16 {
17     G[++num].v=v;G[num].nxt=head[u];G[num].w=1;head[u]=num;
18 }
19 void init()
20 {
21     memset(head,-1,sizeof(head));
22     num=-1;
23 }
24 void spfa(int u)
25 {
26     queue<int>q;
27     memset(dis,inf,sizeof(dis));
28     memset(vis,0,sizeof(vis));
29     q.push(u);
30     vis[u]=1;
31     dis[u]=0;
32     while(!q.empty()){
33         int u=q.front();
34         q.pop();
35         vis[u]=0;
36         for(int i=head[u];i!=-1;i=G[i].nxt){
37             int v=G[i].v;int w=G[i].w;
38             if(dis[v]>dis[u]+w){
39                 dis[v]=dis[u]+w;
40                 if(!vis[v]){
41                     vis[v]=1;
42                     q.push(v);
43                 }
44             }
45         }
46     }
47     if(u==1){
48         for(int i=1;i<=n;i++)
49             disa[i]=dis[i];
50     }
51     else{
52         for(int i=1;i<=n;i++)
53             disb[i]=dis[i];
54     }
55     return;
56 }
57 bool cmp(int x,int y)
58 {
59     return disa[x]-disb[x]<disa[y]-disb[y];
60 }
61 int main()
62 {
63     init();
64     scanf("%d%d%d",&n,&m,&k);
65     for(int i=1;i<=k;i++) scanf("%d",&a[i]);
66     for(int i=1;i<=m;i++){
67         int u,v;
68         scanf("%d%d",&u,&v);
69         add(u,v); add(v,u);
70     }
71     spfa(1);spfa(n);
72     sort(a+1,a+1+k,cmp);
73     int ans=0;
74     int mx=disa[a[1]];
75     for(int i=2;i<=k;i++){
76         ans=max(ans,mx+1+disb[a[i]]);
77         mx=max(mx,disa[a[i]]);
78     }
79     ans=min(ans,disa[n]);
80     printf("%d\n",ans);
81     return 0;
82 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/12383375.html