P2865 [USACO06NOV]路障Roadblocks

题目传送门

这题题意很明确,就是求图的次短路,我用了一个非常奇葩的方法:伟大的分类讨论;

注意,以下说明均针对无向图

首先,图的次短路只有2种情况:

1)1次最短路+乱转(源点->最短路上离其他点最近的点->离它最近的点->返回这个点->终点)

2)直接次短路(依次屏蔽每一条边)

可以证明,无向图的次短路仅有这2种情况,如有错误,请读者在评论区指出

2的情况非常好做,仅需依次屏蔽每一条边(最短路上的)后求最短路就好了,1号情况可以邻接表打擂台去取最小值即可

请读者务必好好理解最短路路径记忆的方法,非常非常重要!!!

参考程序如下:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<queue>
 5 using namespace std;
 6 int n,m,x,y,z,v[200005],w[200005],nxt[200005],head[200005],cnt,dist[200005],pre[200005],edge[200005];
 7 int minn1,lesss,ans,minn2,minn3,ans1=21374404,ans2,ans3,minn4;
 8 int path[100000],num;
 9 bool vis[200005];
10 void add(int a,int b,int c)
11 {
12     v[++cnt]=b;
13     w[cnt]=c;
14     nxt[cnt]=head[a];
15     head[a]=cnt;
16 }
17 void spfa(int s)
18 {
19     memset(dist,20,sizeof(dist));
20     queue<int>q;
21     q.push(s);
22     dist[s]=0;
23     vis[s]=1;
24     while(!q.empty())
25     {
26         int c=q.front();
27         q.pop();
28         vis[c]=0;
29         for(int i=head[c];i;i=nxt[i])
30         {
31             int y=v[i];
32             if(dist[y]>dist[c]+w[i])
33             {
34                 pre[y]=i;edge[y]=c;
35                 dist[y]=dist[c]+w[i];
36                 if(!vis[y])
37                 {
38                     q.push(y);
39                     vis[y]=1;
40                 }
41             }
42         }
43     }
44 }
45 int main()
46 {
47     cin>>n>>m;
48     for(int i=1;i<=m;i++)
49     {
50         cin>>x>>y>>z;
51         add(x,y,z);
52         add(y,x,z);
53     }
54     spfa(1);
55     minn3=dist[n]*3;
56     int s=21370444;
57     for(int i=head[n];i;i=nxt[i])
58     {
59         s=min(s,w[i]*2);
60     } 
61     minn2=dist[n]*2+s;
62     s=21370444;
63     for(int i=head[1];i;i=nxt[i])
64     {
65         s=min(s,w[i]*2);
66     } 
67     minn4=dist[n]*2+s;
68     minn1=dist[n];
69     int now=n;
70     while(now!=1)
71     {
72         path[++num]=pre[now];
73         now=edge[now];
74     }
75     for(int i=1;i<=num;i++)
76     {
77         int s=w[path[i]];
78         w[path[i]]=99999999;
79         spfa(1);
80         lesss=dist[n];
81         if(lesss!=minn1)ans1=min(ans1,lesss);
82         w[path[i]]=s;
83     }
84     ans=min(ans1,min(minn2,min(minn3,minn4)));
85     cout<<ans;
86     return 0;
87 }
View Code

  

原文地址:https://www.cnblogs.com/szmssf/p/10999723.html