ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AcWing 342. 道路与航线

2021-04-28 02:01:13  阅读:221  来源: 互联网

标签:连通 航线 dist int 拓扑 入度 342 road AcWing


原题链接

考察:最短路+拓扑排序

完全不会,fw本f

错误思路:

        一看题,这不spfa裸题吗,结果代码上去TLE.

正确思路:

       有负权边求最短路,又卡SPFA.不考虑SPFA优化的话,似乎是没有办法了.但这道题特地说明了两种边的特性,所以可以从边入手.

       已知双向边无负权边,如果不考虑单向边可以考虑用dijkstra算法.又已知单向边只存在A->B的方式,一定不存在B->A的方式.当我们不考虑单向边,剩下的就是离散的连通块.我们将连通块缩点,再加入单向边.由于单向边不成环,最后一点可以形成拓扑排序.拓扑排序的最短路可以按拓扑排序的顺序求即可.

       那么如何实现上述思路?因为需要考虑拓扑排序,所以按拓扑排序处理,先将入度为0的连通块纳入队列,然后更新该连通块内的最短距离.如果当前点能遍历到其他连通块的点,那么该连通块入度-1,直到入度=0,纳入拓扑队列.

       注意几个坑点:

  1. 不能直接把起点所在连通块放入,这样存在无法更新拓扑序列的情况.
  2. 不能在dist[v]>dist[u]+w的if内判断入度是否为0.按照拓扑排序应该只要能遍历到入度就--.否则后面的连通块不能更新.
  3. 虽然拓扑排序入度可能>1.但是实际图只要有边就可以遍历到其他连通块去,其他块的距离必须被更新,所以只要能遍历到,入度就--
 1 #include <iostream>
 2 #include <cstring>
 3 #include <queue>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 25010,M = 50010,INF = 0x3f3f3f3f;
 7 typedef pair<int,int> PII;
 8 int n,m,sx,s,h[N],idx,dist[N],p[N],id[N],d[N],sz;
 9 bool st[N];
10 vector<int> node[N];
11 struct Road{
12     int fr,to,ne,w;
13 }road[M*3];
14 void add(int a,int b,int w)
15 {
16     road[idx].to = b,road[idx].w = w,road[idx].ne = h[a],h[a] = idx++;
17 }
18 void dfs(int u,int color)
19 {
20     id[u] = color;
21     st[u] = 1;
22     node[color].push_back(u);
23     for(int i=h[u];i!=-1;i=road[i].ne)
24     {
25         int v = road[i].to;
26         if(!st[v]) dfs(v,color);
27     }
28 }
29 void dijkstra(int idx)
30 {
31     priority_queue<PII,vector<PII>,greater<PII> > q;
32     for(int i=0;i<node[idx].size();i++) q.push({dist[node[idx][i]],node[idx][i]});
33     while(q.size())
34     {
35         PII it = q.top();
36         q.pop();
37         int u = it.second;
38         if(st[u]) continue;
39         st[u] = 1;
40         for(int i=h[u];~i;i=road[i].ne)
41         {
42             int v = road[i].to;
43             if(id[v]!=id[u])
44               if(--d[id[v]]==0) node[0].push_back(id[v]);
45             if(dist[v]>dist[u]+road[i].w)
46             {
47                 dist[v] = dist[u]+road[i].w;
48                 if(id[v]==id[u]) q.push({dist[v],v});
49             }
50         }
51     }
52 }
53 void solve()
54 {
55     memset(dist,0x3f,sizeof dist);
56     dist[s] = 0;
57     queue<int> q;
58     for(int i=1;i<=sz;i++)
59       if(!d[i]) q.push(i);
60     while(q.size())
61     {
62         int u = q.front();
63         q.pop();
64         dijkstra(u);
65         for(int i=0;i<node[0].size();i++) q.push(node[0][i]);
66         node[0].clear();
67     }
68 }
69 int main()
70 {
71     scanf("%d%d%d%d",&n,&m,&sx,&s);
72     memset(h,-1,sizeof h);
73     while(m--)
74     {
75         int a,b,c; scanf("%d%d%d",&a,&b,&c);
76         add(a,b,c); add(b,a,c);
77     }
78     for(int i=1;i<=n;i++)
79       if(!id[i]) dfs(i,++sz);
80     memset(st,0,sizeof st);
81     while(sx--)
82     {
83         int a,b,c; scanf("%d%d%d",&a,&b,&c);
84         add(a,b,c); d[id[b]]++;
85     }
86     solve();
87     for(int i=1;i<=n;i++)
88       if(dist[i]>=INF/2) puts("NO PATH");
89       else printf("%d\n",dist[i]);
90     return 0;
91 }

 

标签:连通,航线,dist,int,拓扑,入度,342,road,AcWing
来源: https://www.cnblogs.com/newblg/p/14711596.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有