zoukankan      html  css  js  c++  java
  • POJ 3013 Big Christmas Tree (最短路模型)

    题意:有一些点,每个点都有一个重量值,然后给出了一些边,每个边都有一个权值。最后让用一些边组成一棵树,使得花费最少,每个边(u,v)的花费=(边得所有子孙节点的重量和)*(该边的权值)。(一条边离根远的节点是另一个节点的子节点)   好题,要能看出来是最短路的模型。(这题看着像最小生成树。。) 路径的总花费 = sigma(每条边(u,v)的子孙节点重量和*该点的权值),那么如果按边来看,我们只能从它的子孙节点下手。但是我们不知道最后的树某个边的子孙节点有谁。所以需要一定的策略来算最优值,或者贪心,或者DP。我想这条路应该是行的通的,不过我没有想出来还。。。我用的是另一种大家都用的方法。。。 我们换个角度思考路径的总花费:从节点的角度考虑。对于每个节点来说,把它的重量算进去的边只可能是从根的它的某条路径上的边,这样一来这个节点的最优值就很明显的是从根到这个节点的最短路了。然后大家都懂得。。。  
    #include
    
    #define maxN 50005
    #define inf 10000000000000
    
    struct EDGE 
    {
    	int v,w;
    	int next;
    }edge[2 * maxN];//鄰接表
    
    int preEdge[2 * maxN];//preEdge[u],上一條以u为起點的邊在edge中的位置
    long long dis[maxN];//最短路
    bool vis[maxN];
    int weight[maxN];//節點重量
    int queue[20 * maxN];//松弛隊列
    int n,m;
    
    void Init()//初始化
    {
    	for (int i = 1; i <= n; ++ i)
    	{
    		preEdge[i] = 0;
    		dis[i] = inf;
    		vis[i] = false;
    	}
    }
    
    void spfa()
    {
    	int head = 0, tail = 1;
    	queue[0] = 1;
    	dis[1] = 0;
    	while (head < tail)
    	{
    		int u = queue[head];
    		vis[u] = true;
    		int p = preEdge[u];//以u为起始點 鄰接表中第幾條邊
    		while (p != 0)
    		{
    			int v = edge[p].v, w = edge[p].w;
    			if (dis[v] > dis[u] + w)
    			{
    				dis[v] = dis[u] + w;
    				if (!vis[v])
    				{
    					vis[v] = true;
    					queue[tail] = v;
    					tail ++;
    				}
    			}
    			p = edge[p].next;//下一條以u起點的邊
    		}
    		head ++;
    		vis[u] = false;
    	}
    	bool flag = true;
    	long long  sum = 0;
    	for (int i = 2; i <= n; ++ i)
    	{
    		if (dis[i] == inf)
    		{
    			flag = false;
    			break;
    		}
    		sum += weight[i] * dis[i];
    	}
    	if (!flag)
    	{
    		printf("No Answer\n");
    	}
    	else
    		printf("%lld\n", sum);
    
    
    }
    
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while (t --)
    	{
    		scanf("%d%d", &n, &m);
    		for (int i = 1; i <= n; ++ i)
    		{
    			scanf("%d", &weight[i]);
    		}
    		Init();
    		int index = 1;
    		for (int i = 1; i <= m; ++ i)
    		{
    			int a, b, c;
    			scanf("%d%d%d", &a, &b, &c);
    			edge[index].v = b;
    			edge[index].w = c;
    			edge[index].next = preEdge[a];
    			preEdge[a] = index ++;
    
    			edge[index].v = a;
    			edge[index].w = c;
    			edge[index].next = preEdge[b];
    			preEdge[b] = index ++;
    
    		}
    		if (n == 0 || n == 1)
    		{
    			printf("0\n");
    			continue;
    		}
    		spfa();
    	}
    	return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    Unstar A File:
    star 一个文件
    列出大星号文件
    删除用户
    curl -d
    创建用户
    Check Account Info
    List Accounts
    认证ping
    python 解接口返回的json字符串
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114239.html
Copyright © 2011-2022 走看看