[关闭]
@AkamemakA 2022-07-03T14:08:56.000000Z 字数 1915 阅读 266

Atcoder 题解

Atcoder Beginner Contest 257 problem F 题解


题目链接:点我

题目大意

个城镇,编号为

条路,第条路连接城镇和城镇。每条路是双向的。一个人经过一条路从一边走到另一边需要分钟。但对于某些道路,如果其,则代表这条路的一边连接着,但另一边不确定。

对于每一个,回答以下问题:

如果所有的有不确定城镇的道路都连接到城镇,那么一个人需要多少分钟才能从城镇走到城镇?输出这个时间。如果无法走到,则输出

样例输入1

  1. 3 2
  2. 0 2
  3. 1 2

样例输出1

  1. -1 -1 2

样例解释1

如果所有的未确定道路都连接到城镇,则道路和道路都连接了城镇。是不可能从城镇走到城镇的。

如果所有的未确定道路都连接到城镇,则道路连接了号城镇自己,道路连接了城镇,也是不可能从城镇走到城镇的。

如果所有的未确定道路都连接到城镇,则道路连接了城镇,道路连接了城镇,于是可以从用分钟城镇走到城镇

因此输出为

请注意,确定了不确定的道路连接到的城镇,可能有一条道路连接城镇和城镇本身,也可能有多条道路连接同一对城镇。

样例输入2

  1. 5 5
  2. 1 2
  3. 1 3
  4. 3 4
  5. 4 5
  6. 0 2

样例输出2

  1. 3 3 3 3 2

数据范围


解析

一道美丽的图论题。

构造一个图,并且构造一个城镇。如果一条道路的一端连到了不确定的端点,那么就直接连上城镇。当我们确定这个不确定的城镇时,那么就相当于在城镇与城镇之间连接了一条长度为的虚拟边。

定义为城镇道城镇之间需要的时间。如果,则代表之间不能到达。

当回答第个询问时,如果不需要经过城镇就可以从城镇走到城镇的话,那么一个备选答案就是

否则,需要经过城镇的话,那么答案就为或者是。三者当中选最小值。

可以用下图作为参考。

img

由于我们在实现过程中,只会用到以为起点的值,因此我们可以跑两次bfs来计算出城镇值。


代码实现

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=3e5+5,INF=0x3f3f3f3f; //INF表示正无穷,即两边不可到达
  4. int n,m;
  5. int he[N],ne[N<<1],go[N<<1],val[N<<1],tot; //前向星
  6. int vis[N],dis1[N],disn[N]; //vis为标记数组,dis1和disn分别表示从1和n开始的dis值
  7. inline void add(int a,int b,int c){
  8. ne[++tot]=he[a];he[a]=tot;go[tot]=b;val[tot]=c;
  9. } //加边
  10. inline void bfs(int s,int *dis){
  11. memset(vis,0,sizeof vis);
  12. dis[s]=0;
  13. queue<int>q;
  14. q.push(s);
  15. vis[s]=1;
  16. while(!q.empty()){
  17. int u=q.front();
  18. q.pop();
  19. for(int i=he[u];i;i=ne[i]){
  20. int v=go[i];
  21. if(!vis[v]){
  22. q.push(v);vis[v]=1;
  23. dis[v]=dis[u]+val[i]; //计算dis
  24. }
  25. }
  26. }
  27. }
  28. int main(){
  29. cin>>n>>m;
  30. for(int i=1;i<=m;i++){
  31. int u,v;
  32. scanf("%d%d",&u,&v);
  33. add(u,v,1);add(v,u,1);
  34. }
  35. memset(dis1,INF,sizeof dis1);
  36. memset(disn,INF,sizeof disn); //开始时全不可达
  37. bfs(1,dis1);
  38. bfs(n,disn); //bfs找到dis值
  39. for(int i=1;i<=n;i++){
  40. int ans=min(dis1[n],min(dis1[0]+disn[i],dis1[i]+disn[0])); //具体见图
  41. if(ans==INF) cout<<-1<<" "; //如果不可达
  42. else cout<<ans<<" ";
  43. }
  44. return 0;
  45. }

完结撒花~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注