汕头市赛srm8 C-3

n<=100000个点m<=300000条边有权无向联通图,给出K<=10000个特殊点求K个点中任意两点最短路的最小值。

方法一:K小,随便搞。先构造最短路树,在最短路树上Dijkstra,遇到第一个特殊点就返回。代码如下:

如下个头。首先时间复杂度显然超了,其次建树时要考虑重边,比较难搞。

方法二:多源最短路。

插播:多源最短路方法:把每个源加进初始队列即可。

(1)利用多源最短路求出每个特殊点到其它点的最短路和次短路,利用两个的和来更新。一位大神在比赛中用该方法A过。

(2)直接求每个特殊点到其它点的最短路,把Dijkstra中的vis数组去掉,就是凡是松弛过的点都扔进优先队列里,然后,在松弛前,如果该点已经有最短路了,(我认为)现在访问的这条路径是次短路,直接更新答案。

注意不能用  来自同个特殊点的最短路  更新答案,所以记每个点的最短路来自哪个特殊点。

(3)随机化。把K分成两部分S,T,求S到T的最短路,这样得到正确答案的概率为1/2,多分几次就可以把错误概率降到极低。

代码为方法二(2)。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<queue>
 6 //#include<iostream>
 7 using namespace std;
 8 
 9 int n,m,K;
10 #define maxn 100011
11 #define maxm 600011
12 const int inf=0x7fffffff;
13 struct Edge{int to,v,next;};
14 struct Graph
15 {
16     Edge edge[maxm];int le;
17     int first[maxn],dis[maxn],id[maxn],start[maxn];bool vis[maxn];
18     Graph()
19     {
20         memset(first,0,sizeof(first));
21         le=2;
22     }
23     void add_edge(int x,int y,int v)
24     {
25         Edge &e=edge[le];
26         e.to=y;e.v=v;
27         e.next=first[x];
28         first[x]=le++;
29     }
30     void insert(int x,int y,int v)
31     {
32         add_edge(x,y,v);
33         add_edge(y,x,v);
34     }
35     struct heapnode
36     {
37         int x,v;
38         bool operator < (const heapnode &b) const {return v<b.v;}
39         bool operator > (const heapnode &b) const {return v>b.v;}
40     };
41     priority_queue<heapnode,vector<heapnode>,greater<heapnode> > q;
42     int ans;
43     int dijkstra()
44     {
45         for (int i=1;i<=n;i++) dis[i]=inf;
46         memset(id,0,sizeof(id));
47         for (int i=1;i<=K;i++)
48         {
49             dis[start[i]]=0;
50             id[start[i]]=start[i];
51             q.push((heapnode){start[i],0});
52         }
53         ans=inf;
54         while (!q.empty())
55         {
56             const int now=q.top().x,d=q.top().v;
57             q.pop();
58             if (d!=dis[now]) continue;
59             for (int i=first[now];i;i=edge[i].next)
60             {
61                 const Edge &e=edge[i];
62                 if (dis[e.to]!=inf && id[now]!=id[e.to])
63                     ans=min(ans,dis[e.to]+d+e.v);
64                 if (dis[e.to]>d+e.v)
65                 {
66                     dis[e.to]=d+e.v;
67                     id[e.to]=id[now];
68                     q.push((heapnode){e.to,dis[e.to]});
69                 }
70             }
71         }
72         return ans;
73     }
74 }G;
75 int x,y,v;
76 int main()
77 {
78     scanf("%d%d%d",&n,&m,&K);
79     for (int i=1;i<=K;i++) scanf("%d",&G.start[i]);
80     for (int i=1;i<=m;i++)
81     {
82         scanf("%d%d%d",&x,&y,&v);
83         G.insert(x,y,v);
84     }
85     printf("%d\n",G.dijkstra());
86     return 0;
87 }
View Code

 

posted @ 2017-07-27 17:26  Blue233333  阅读(150)  评论(0编辑  收藏  举报