B. Highways
题目大意
有许多城市被连接在高速路网当中,每条路都有相应的最短通行时间,现在给定起点和终点,要求给出从起点到终点的最短通行时间。
A number of cities are connected by a network of highways. Each highway is bidirectional and connects two cities, with a given travel time. What is the shortest time to get from a given city to another given city?
Input
The first line of input contains the number of test cases.
Each test case starts with a line containing the number of cities n (2 ≤ n ≤ 100000), the number of highways m (1 ≤ m ≤ 100000), the starting city and the ending city. Cities are numbered from 1 to n.
Then m lines follow, each describing one highway. The description consists of the two distinct city numbers and the time in minutes to travel along the highway. The time will be between 1 and 1000.
Output
For each test case output a single line containing the minimum time it takes to get from the start to the destination. If no connection exists, output NONE.
Example
Input: 2 4 2 1 4 1 2 5 3 4 5 4 4 1 4 1 2 5 2 3 5 3 4 5 4 2 6 Output: NONE 11
做法
图论入门,Dijkstra算法求最短路模板题,用数组模拟邻接表建边,edges数组保存边的具体数据,而G数组只保存该点的某条边在edges数组中的下标,dijkstra函数从起点和与起点直接连接的点开始遍历整个图。
这道题可能无解。memset在ctring头文件里。
AC-Code (C++)
Time: 40 ms Memory: 20.5 MB
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<cmath>
#include<functional>
using namespace std;
const int MAXN = 100000 + 10;
const int INF = 100000000;
int t; //测试数
int n; //城市总数
int m; //道路总数
int start; //起点城市
int ending; //终点城市
int mm;
struct Edge
{
int from, to, dist;
Edge(int u, int v, int d) :from(u), to(v), dist(d){}
};
vector<Edge> edges;
vector<int> G[MAXN]; //G[x]记录与x有边的y1,y2...等在edges数组中的下标
bool done[MAXN];
typedef pair<int, int> P;
int d[MAXN]; //该点到start的最短时间
void init(int x)
{
n = x;
for (int i = 0; i < n; i++)
G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int dist)
{
edges.push_back(Edge(from, to, dist));
mm = edges.size();
G[from].push_back(mm - 1);
}
void dijkstra(int s)
{
priority_queue<P, vector<P>, greater<P> > Q;
for (int i = 1; i <= n; i++) d[i] = INF;
d[s] = 0;
for (int i = 1; i <= n; i++)
done[i] = false;
Q.push(P(0, s));
while (!Q.empty())
{
P x = Q.top();
Q.pop();
int u = x.second; //当前结点编号
if (done[u]) continue;
done[u] = true;
for (int i = 0; i < G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
if (d[e.to]>d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
Q.push(P(d[e.to], e.to));
}
}
}
}
int main(void)
{
scanf("%d", &t);
while (t--)
{
scanf("%d %d %d %d", &n, &m, &start, &ending);
init(n);
for (int i = 0; i < m; i++)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
AddEdge(a, b, c);
AddEdge(b, a, c);
}
dijkstra(start);
if (d[ending] == INF)
printf("NONE\n");
else
printf("%d\n", d[ending]);
//for (int i = 1; i <= n; i++)
//printf("d[%d]=%d\n", i, d[i]);
}
//system("PAUSE");
return 0;
}
E . Tree
题目大意
二叉树上各节点的权值都各不相同,现给定一颗二叉树的中序遍历和后序遍历,要求该二叉树从根节点到某叶节点的权值之和的最大值,如果有多解,则取叶节点权值最小的点,最终输出该叶节点的权值。做法
因为权值各不相同,所以用权值来代替结点编号,二叉树后序遍历的最后一个值即为根节点,在中序遍历中找到根节点即可确定左子树和右子树,递归进行此操作就可以由中序遍历和后序遍历唯一地确定一棵二叉树,最后用dfs遍历该树得到最大的和值和限制条件下最小的叶节点。AC-Code (C++)
Time: 80 ms
/*
**此题为用后序遍历和中序遍历建树,
**递归遍历该树的模板题,
**务必记下!!!
*/
#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std;
const int maxv = 10000 + 10;
int in_order[maxv], post_order[maxv], lch[maxv], rch[maxv];
int n;
bool read_list(int* a)
{
string line;
if (!getline(cin, line)) return false;
stringstream ss(line);
n = 0;
int x;
while (ss >> x) a[n++] = x;
return n > 0;
}
//把in_order[L1...R1]和post_order[L2...R2]建成一棵树,返回树根
int build(int L1, int R1, int L2, int R2)
{
if (L1 > R1) return 0; //空树
int root = post_order[R2];
int p = L1;
while (in_order[p] != root) p++; //此后p为根节点在in_order数组中的下标
int cnt = p - L1; //左子树结点的个数
lch[root] = build(L1, p - 1, L2, L2 + cnt - 1);
rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1);
return root;
}
int best, best_sum;
void dfs(int u, int sum)
{
sum += u;
if (!lch[u] && !rch[u])
{
if (sum < best_sum || (sum == best_sum && u < best))
{
best = u;
best_sum = sum;
}
}
if (lch[u]) dfs(lch[u], sum);
if (rch[u]) dfs(rch[u], sum);
}
int main(void)
{
while (read_list(in_order))
{
read_list(post_order);
build(0, n - 1, 0, n - 1);
best_sum = 1000000000;
dfs(post_order[n - 1], 0);
cout << best << "\n";
}
return 0;
}