Big Christmas Tree

Description

Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of the tree is shown in right picture.

The tree can be represented as a collection of numbered nodes and some edges. The nodes are numbered 1 through
n. The root is always numbered 1. Every node in the tree has its weight. The weights can be different from each other. Also the shape of every available edge between two nodes is different, so the unit price of each edge is different. Because of a
technical difficulty, price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge).

Suby wants to minimize the cost of whole tree among all possible choices. Also he wants to use all nodes because he wants a large tree. So he decided to ask you for helping solve this task by find the minimum cost.

Input

The input consists of T test cases. The number of test cases T is given in the first line of the input file. Each test case consists of several lines. Two numbers
v, e (0 ≤ v, e ≤ 50000) are given in the first line of each test case. On the next line,
v positive integers wi indicating the weights of
v
nodes are given in one line. On the following e lines, each line contain three positive integers
a, b, c indicating the edge which is able to connect two nodes
a and b, and unit price c.

All numbers in input are less than 216.

Output

For each test case, output an integer indicating the minimum possible cost for the tree in one line. If there is no way to build a Christmas tree, print “No Answer” in one line.

Sample Input

2
2 1
1 1
1 2 15
7 7
200 10 20 30 40 50 60
1 2 1
2 3 3
2 4 2
3 5 4
3 7 2
3 6 3
1 5 9

Sample Output

15
1210

题解:其实就是求最短路径,反正我是没读懂,看来别人的感觉和题目说的完全不同。

SPFA(数组邻接表):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>

using namespace std; 

const long long INF = 0x3ffffffffffff;

struct Node
{
	int to;
	int cost;
	Node(){
	}
	Node(int a,int b)
	{
		to = a;
		cost = b;
	}
};

int first[50005];
int next[100005];
Node e[100005];
bool visited[50005];
long long d[50005];
long long w[50005];

void spfa(int n)
{
	memset(visited,false,sizeof(visited));
	for(int i = 1;i <= n;i++)
	{
		d[i] = INF;
	}
	d[1] = 0;
	queue<int> q;
	q.push(1);
	visited[1] = true;
	while(!q.empty())
	{
		int x = q.front();
		q.pop();
		visited[x] = false;
		for(int i = first[x];i != -1;i = next[i])
		{
			int t = e[i].to;
			if(d[t] > d[x] + e[i].cost)
			{
				d[t] = d[x] + e[i].cost;
				if(!visited[t])
				{
					q.push(t);
					visited[t] = true;
				}
			}
		}
	}
}

int main()
{
	int ncase;
	cin>>ncase;
	while(ncase--)
	{
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i = 1;i <= n;i++)
		{
			first[i] = -1;
			scanf("%lld",w + i);
		}
		int k = 0;
		for(int i = 0;i < m;i++)
		{
			int u,v,c;
			scanf("%d%d%d",&u,&v,&c);
			e[k].to = v;
			e[k].cost = c;
			next[k] = first[u];
			first[u] = k++;
			e[k].to = u;
			e[k].cost = c;
			next[k] = first[v];
			first[v] = k++;
		}

		if(n == 0 || m == 0)
		{
			printf("0\n");
			continue;
		}
		spfa(n);
		bool flag = true;
		long long ans = 0;
		for(int i = 1;i <= n;i++)
		{
			if(d[i] == INF)
			{
				flag = false;
				break;
			}
			ans += d[i] * w[i];
		}
		if(flag)
		{
			printf("%lld\n",ans);
		}
		else
		{
			printf("No Answer\n");
		}
	}

	return 0;
}

djistra(数组邻接表):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>

using namespace std; 

const __int64 INF = 10000000000;

struct Node
{
	int to;
	__int64 cost;
	Node(){
	}
	Node(int a,__int64 b)
	{
		to = a;
		cost = b;
	}
	bool operator< (Node t) const
	{
		return cost > t.cost;
	}
};
int first[50005];
int next[100005];
Node e[100005];
bool visited[50005];
__int64 d[50005];
__int64 w[50005];
__int64 ans = 0;

void djistra(int n)
{
	memset(visited,false,sizeof(visited));
	for(int i = 1;i <= n;i++)
	{
		d[i] = INF;
	}
	d[1] = 0;
	priority_queue<Node> q;
	q.push(Node(1,0));
	ans = 0;
	int cnt = 0;
	while(!q.empty())
	{
		Node p = q.top();
		q.pop();
		if(visited[p.to])
		{
			continue;
		}
		cnt++;
		ans += d[p.to] * w[p.to];
		visited[p.to] = true;
		for(int i = first[p.to];i != -1;i = next[i])
		{
			int x = e[i].to;
			if(!visited[x] && d[x] > d[p.to] + e[i].cost)
			{
				d[x] = d[p.to] + e[i].cost;
				q.push(Node(x,d[x]));
			}
		}
	}
	if(cnt != n)
	{
		ans = -1;
	}
}

int main()
{
	int ncase;
	cin>>ncase;
	while(ncase--)
	{
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i = 1;i <= n;i++)
		{
			first[i] = -1;
			scanf("%I64d",w + i);
		}
		int k = 0;
		for(int i = 0;i < m;i++)
		{
			int u,v;
			__int64 c;
			scanf("%d%d%I64d",&u,&v,&c);
		    e[k].to = v;
			e[k].cost = c;
			next[k] = first[u];
			first[u] = k++;
			e[k].to = u;
			e[k].cost = c;
			next[k] = first[v];
			first[v] = k++;
		}
		if(n == 0 || n == 1)
		{
			printf("0\n");
			continue;
		}
		djistra(n);
		if(ans != -1)
		{
			printf("%I64d\n",ans);
		}
		else
		{
			printf("No Answer\n");
		}
	}

	return 0;
}

超时vector:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <utility>

using namespace std; 

const __int64 INF = 0x3fffffffffff;

struct Node
{
	int to;
	int cost;
	Node(){
	}
	Node(int a,int b)
	{
		to = a;
		cost = b;
	}
	bool operator< (Node t) const
	{
		return cost > t.cost;
	}
};
typedef pair<__int64,int>plli;
priority_queue<plli , vector<plli> , greater<plli> > q;

vector<Node> vec[50005];
bool visited[50005];
__int64 d[50005];
int w[50005];
__int64 ans;

void djistra(int n)
{
	memset(visited,false,sizeof(visited));
	for(int i = 1;i <= n;i++)
	{
		d[i] = INF;
	}
	d[1] = 0;
	ans = 0;
	priority_queue<Node> q;
	q.push(Node(1,0));
	int cnt = 0;
	while(!q.empty())
	{
		Node p = q.top();
		q.pop();
		if(visited[p.to])
		{
			continue;
		}
		ans += w[p.to] * d[p.to];
		cnt++;
		visited[p.to] = true;
		for(int i = 0;i < vec[p.to].size();i++)
		{
			int x = vec[p.to][i].to;
			if(!visited[x] && d[x] > d[p.to] + vec[p.to][i].cost)
			{
				d[x] = d[p.to] + vec[p.to][i].cost;
				q.push(Node(x,d[x]));
			}
		}
	}
	if(cnt != n)
	{
		ans = -1;
	}
}

int main()
{
	int ncase;
	cin>>ncase;
	while(ncase--)
	{
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i = 1;i <= n;i++)
		{
			scanf("%d",w + i);
		}
		for(int i = 0;i < m;i++)
		{
			int u,v,c;
			scanf("%d%d%d",&u,&v,&c);
			vec[u].push_back(Node(v,c));
			vec[v].push_back(Node(u,c));
		}
		if(n == 0 || m == 0)
		{
			printf("0\n");
			continue;
		}
		djistra(n);
		if(ans != -1)
		{
			printf("%I64d\n",ans);
		}
		else
		{
			printf("No Answer\n");
		}

		for(int i = 1;i <= n;i++)
		{
			vec[i].clear();
		}

	}

	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 15:13:53

Big Christmas Tree的相关文章

POJ3013 Big Christmas Tree[转换 最短路]

Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23387   Accepted: 5063 Description Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of t

poj 3013 Big Christmas Tree

Big Christmas Tree 题意:输入v个节点和e条边(0 ≤ v, e ≤ 50000) 的图,第二行输入每个节点的权值,之后e行输入每条边的端点和权值: 问是否能找出一棵树,使得树中的边权乘以该边下面的子孙节点权值之和的sigma总和最小:(树以1为根节点) Sample Input 1 200 10 20 30 40 50 60 1 2 1 2 3 3 2 4 2 3 5 4 3 7 2 3 6 3 1 5 9 (删掉) Sample Output 1210 分析:如果计算最小乘

poj3013 Big Christmas Tree --- 最短路

我都不好意思在标题上写这是最短路 这题挺有意思,关键在于把题目所求的量转换为最短路问题. 题意: 给一个无向图,每个结点有权值p[i],每条边有权值w[i] 求使这颗树所有顶点与根节点1联通的最小花费, 最小花费=∑w[i]×∑p[i] 第一个∑是所有边,第二个∑是该边下所有结点的权值和 思路: 通过推导可以发现,对于每个结点,它被算入的花费为 p[i]*d[i], d[i]为该结点到根结点的距离. 于是豁然开朗了吧..水题一道 唯一的坑点是要int64,而且inf要足够大 #include<c

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA)

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n,树根为编号1,选择一些边,使得所有节点构成一棵树,选择边的代价是(子孙的点的重量)×(这条边的价值).求代价最小多少. 分析: 单看每个点被计算过的代价,很明显就是从根到节点的边的价值.所以这是个简单的单源最短路问题. 不过坑点还是很多的. 点的数量高达5w个,用矩阵存不行,只能用边存. 还有路径和结

POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n.树根为编号1,选择一些边.使得全部节点构成一棵树.选择边的代价是(子孙的点的重量)×(这条边的价值). 求代价最小多少. 分析: 单看每一个点被计算过的代价,非常明显就是从根到节点的边的价值.所以这是个简单的单源最短路问题. 只是坑点还是非常多的. 点的数量高达5w个,用矩阵存不行.仅仅能用边存. 还

POJ Big Christmas Tree(最短的基础)

Big Christmas Tree 题目分析: 叫你构造一颗圣诞树,使得 (sum of weights of all descendant nodes) × (unit price of the edge)尽量的小.转换后就是求根节点到每一个节点的距离最短,也就是最短路. 生成树可能会超时.我没试过.然后,求解最短路要用优化的解法不然会超时.最后的答案就是:sum = w[1] * dist[1] + w[2] * dist[2] + ..... w[n] * dist[n].能够自己推推例

poj 3031 Big Christmas Tree(水spfa)

http://poj.org/problem?id=3013 题意: Because of a technical difficulty, price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge).这句话一直没看懂.后面还以为是最小生成树. 正确题意是:给一个无向图,计算每个点到1节点的最短路径(dis[i]) * 每个节点的weights之和. 注意:边权值等要用__

poj 3013 Big Christmas Tree (dij+优先队列优化 求最短路)

模板 题意:给你一个图,1总是为根,每个边有单位价值,每个点有权重. 每条边的价值 = sum(后继节点权重)*边的单位价值. 求树的最小价值,即构成一棵树的n-1条边的最小价值. 算法: 1.因为每个边的价值都要乘以后来访问的节点的权重,而走到后来访问的点必经过这条边. 实际上总价值就是  到每个点的最短路径*这个点的权重. 2.但是这个题 数据量真的太大了,50000个点,50000条边. 写普通的dij算法tle. 必须加优先队列优化- - 据说spfa也能过,但是spfa算法不稳定- -

POJ 3013 Big Christmas Tree【最短路变形,DIjkstra堆优化+spfa算法】

Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23064   Accepted: 4987 Description Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of t