POJ3114 Countries in War (强连通分量 + 缩点 + 最短路径 + 好题)

题目链接

题意是说在几个邮局之间传送一份信件,如果出发点和终止点在同一个国家传递,则时间为0,否则让你求花费最少时间,如果不能传到,则输出Nao e possivel entregar a carta。判断邮局是否在同一个国家的依据是发出的信件可以相互到达。
如果直接求最短路则无法判断两个邮局是否在同一个国家,判断两个邮局是否属于同一个国家的标志是在这个国家邮局间可以相互到达,那么这就是强连通了,所以要先缩点判读邮局是否在同一个国家,如果不是,则重新建图,建图的时候要维护好边权,求出最短边权,在用dijkstra求出最短路即可。
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <vector>
  6 using namespace std;
  7 const int Max = 505;
  8 const int INF = 0x3f3f3f3f;
  9 int n, m, dfs_clock, scc_cnt, scnt;
 10 int g[Max][Max], pre[Max], low[Max], Stack[Max], sccno[Max];
 11 int G[Max][Max];
 12 int head[Max], num;
 13 struct Edge
 14 {
 15     int v, Next;
 16 };
 17 Edge edge[Max * Max];
 18 void addEdge(int u, int v)
 19 {
 20     edge[num].v = v;
 21     edge[num].Next = head[u];
 22     head[u] = num++;
 23 }
 24 void init()
 25 {
 26     memset(head, -1, sizeof(head));
 27     memset(pre, 0, sizeof(pre));
 28     //memset(low, 0, sizeof(low));
 29     memset(sccno, 0, sizeof(sccno));
 30     scnt = dfs_clock = scc_cnt = num = 0;
 31     for (int i = 1; i <= n; i++)
 32         for (int j = i; j <= n; j++)
 33         {
 34             if (i == j)
 35                 G[i][j] = g[i][j] = 0;
 36             else
 37             {
 38                 g[i][j] = g[j][i] = INF;
 39                 G[i][j] = G[j][i] = INF;
 40             }
 41         }
 42 }
 43 void dfs(int u)
 44 {
 45     pre[u] = low[u] = ++dfs_clock;
 46     Stack[scnt++] = u;
 47     for (int i = head[u]; i != -1; i = edge[i].Next)
 48     {
 49         int v = edge[i].v;
 50         if (!pre[v])
 51         {
 52             dfs(v);
 53             low[u] = min(low[u], low[v]);
 54         }
 55         else if (!sccno[v])
 56             low[u] = min(low[u], pre[v]);
 57     }
 58     if (low[u] == pre[u])
 59     {
 60         scc_cnt++;
 61         for (; ;)
 62         {
 63             int x = Stack[--scnt];
 64             sccno[x] = scc_cnt;
 65             if ( x == u)
 66                 break;
 67         }
 68     }
 69 }
 70 void find_scc()
 71 {
 72     for (int i = 1; i <= n; i++)
 73     {
 74         if (!pre[i])
 75             dfs(i);
 76     }
 77 }
 78 void build_new_graphic()
 79 {
 80     for (int i = 1; i <= n; i++)
 81     {
 82         for (int j = 1; j <= n; j++)
 83         {
 84             if (i != j && sccno[i] != sccno[j] && g[i][j] != INF) // 不同的连通分量号建立一条有向边。
 85             {
 86                 G[ sccno[i] ][ sccno[j] ] = min(g[i][j], G[ sccno[i] ][ sccno[j] ]);
 87             }
 88         }
 89     }
 90 }
 91 int dist[Max], vis[Max];
 92 void dijkstra(int start, int goal)
 93 {
 94    //利用起点start,终点goal来搞,以前做惯了,直接用起点是1来做了
 95     for (int i = 1; i <= scc_cnt; i++)
 96         dist[i] = G[start][i]; 
 97     memset(vis, 0, sizeof(vis));
 98     dist[start] = 0;
 99     vis[start] = 1;
100     for (int i = 2; i <= scc_cnt; i++)
101     {
102         int minn = INF, pos = 1; // 这里初始化pos为1,否则当下面的循环不满足条件是,执行vis[pos]会出错
103         for (int j = 1; j <= scc_cnt; j++)
104         {
105             if (!vis[j] && minn > dist[j])
106             {
107                 minn = dist[j];
108                 pos = j;
109             }
110         }
111         vis[pos] = 1;
112         for (int j = 1; j <= scc_cnt; j++)
113         {
114             if (!vis[j] && dist[j] > dist[pos] + G[pos][j])
115                 dist[j] = dist[pos] + G[pos][j];
116         }
117     }
118     if (dist[goal] != INF)
119         printf("%d\n", dist[goal]);
120     else
121         printf("Nao e possivel entregar a carta\n");
122 }
123 int main()
124 {
125     while (scanf("%d%d", &n, &m) != EOF)
126     {
127         if (n == 0 && m == 0)
128             break;
129         init();
130         int u, v, c;
131         for (int i = 1; i <= m; i++)
132         {
133             scanf("%d%d%d", &u, &v, &c);
134             if (g[u][v] > c)
135             {
136                 g[u][v] = c;  // 判断重边
137             }
138             addEdge(u, v);
139         }
140         find_scc();  // 找强连通分量
141         //cout << scc_cnt << endl;
142         build_new_graphic();  // 重新构图
143 
144         int k;
145         scanf("%d", &k);
146         while (k--)
147         {
148             scanf("%d%d", &u, &v);
149             if (sccno[u] == sccno[v])  // 同一连通分量直接输出
150                 printf("0\n");
151             else
152             {
153                 dijkstra(sccno[u], sccno[v]);
154             }
155         }
156         printf("\n");
157     }
158 
159     return 0;
160 }
View Code

 

转载于:https://www.cnblogs.com/zhaopAC/p/5351773.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值