WHUST 2017 Div.2 Day 9 [2017-07-29]

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

UVA - 548

        二叉树上各节点的权值都各不相同,现给定一颗二叉树的中序遍历和后序遍历,要求该二叉树从根节点到某叶节点的权值之和的最大值,如果有多解,则取叶节点权值最小的点,最终输出该叶节点的权值。

        因为权值各不相同,所以用权值来代替结点编号,二叉树后序遍历的最后一个值即为根节点,在中序遍历中找到根节点即可确定左子树和右子树,递归进行此操作就可以由中序遍历和后序遍历唯一地确定一棵二叉树,最后用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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值