zoukankan      html  css  js  c++  java
  • P2916 [USACO08NOV]安慰奶牛Cheering up the Cow

    P2916 [USACO08NOV]安慰奶牛Cheering up the Cow

    同步:https://buringstraw.win/index.php/archives/36/

    题目描述

    约翰有N个牧场,编号依次为1到N。每个牧场里住着一头奶牛。连接这些牧场的有P条道路,每条道路都是双向的。第j条道路连接的是牧场Sj和Ej,通行需要Lj的时间。两牧场之间最多只有一条道路。约翰打算在保持各牧场连通的情况下去掉尽量多的道路。

    约翰知道,在道路被强拆后,奶牛会非常伤心,所以他计划拆除道路之后就去忽悠她们。约翰可以选择从任意一个牧场出发开始他维稳工作。当他走访完所有的奶牛之后,还要回到他的出发地。每次路过牧场i的时候,他必须花Ci的时间和奶牛交谈,即使之前已经做过工作了,也要留下来再谈一次。注意约翰在出发和回去的时候,都要和出发地的奶牛谈一次话。请你计算一下,约翰要拆除哪些道路,才能让忽悠奶牛的时间变得最少?

    输入输出格式

    输入格式:

    * Line 1: Two space-separated integers: N and P

    * Lines 2..N+1: Line i+1 contains a single integer: C_i

    * Lines N+2..N+P+1: Line N+j+1 contains three space-separated

    integers: S_j, E_j, and L_j

    输出格式:

    * Line 1: A single integer, the total time it takes to visit all the cows (including the two visits to the cow in your

    sleeping-pasture)

    输入输出样例

    输入样例#1:

    5 7 
    10 
    10 
    20 
    6 
    30 
    1 2 5 
    2 3 5 
    2 4 12 
    3 4 17 
    2 5 15 
    3 5 6 
    4 5 12 
    

    输出样例#1:

    176 
    

    说明

       +-(15)-+ 
      /         
     /           
    1-(5)-2-(5)-3-(6)--5 
          /(17)  / 
    (12) /      /(12) 
         4------+ 
    
    Keep these paths: 
    1-(5)-2-(5)-3      5 
                     / 
        (12)        /(12) 
            *4------+ 
    

    Wake up in pasture 4 and visit pastures in the order 4, 5, 4, 2, 3, 2, 1, 2, 4 yielding a total time of 176 before going back to sleep.

    思路

    我发现把边权设为走路的时间加上两端谈话的时间,排序之后求最小生成树的选边结果(样例)跟样例答案一样。

    所以打算按这样求出选哪些边之后dfs求总时间。

    告诉hqx大佬,大佬经过严密的推论,发现只要把边权设为两倍路上时间加一倍的两端时间,最小生成树的和加上最少的一个点的谈话时间,就是最短总时间。

    理由是来回每条边都会经过两次(观察样例/造数据),分别消耗的是两个端点的时间。出发点会多算一次。

    HQX大佬TQL!

    CODE

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    
    const int MAXN=1000000+5,INF=0x3f3f3f3f;
    
    int n,p;
    int c[10005];
    
    struct tu
    {	
    	struct edge
    	{
    		int p1,p2,w,a;
    		friend bool operator <(edge x,edge y)
    		{
    			return x.a<y.a;
    		}
    	} b[MAXN];
    	
    	
    	int newpe;
    	int head[MAXN];
    	int fa[MAXN];
    	bool v[MAXN];
    	
    	void insert(int p1,int p2,int w)
    	{
    		b[++newpe].p1=p1;
    		b[newpe].p2=p2;
    		b[newpe].w=w;
    		b[newpe].a=2*b[newpe].w+c[p1]+c[p2];
    	}
    	
    	int zxscs(void)//最小生成树(原谅我不会打克鲁斯卡尔)
    	{
    		sort(b+1,b+1+newpe);
    		for(int i=1;i<=n;++i)
    		{
    			fa[i]=i;
    		}
    		int cnt=0;
    		int tot=0;
    		for(int i=1;i<=newpe;++i)
    		{
    			if(doFind(b[i].p1)!=doFind(b[i].p2))
    			{
    				++cnt;
    				tot+=b[i].a;
    				doUnion(b[i].p1,b[i].p2);
    			}
    			if(cnt==n-1)
    			{
    				return tot;
    			}
    		}
    		return 0;
    	}
    	
    	void doUnion(int x,int y)
    	{
    		x=doFind(x);
    		y=doFind(y);
    		fa[x]=y;
    	}
    	
    	int doFind(int x)
    	{
    		if(fa[x]==x)return x;
    		else return fa[x]=doFind(fa[x]);
    	}
    	
    } mp;
    int main(void)
    {
    	scanf("%d%d",&n,&p);
    	int minc=INF;
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%d",c+i);
    		minc=min(c[i],minc);
    	}
    	
    	for(int i=1;i<=p;++i)
    	{
    		int p1,p2,w;
    		scanf("%d%d%d",&p1,&p2,&w);
    		mp.insert(p1,p2,w);
    	}
    	int ans;
    	ans=mp.zxscs();
    	ans+=minc;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    LeetCode: Tags-[Array], Difficulty-[Medium]
    J2SE 常用方法
    LeetCode: Tags-[Array], Difficulty-[Easy]
    Java Code Style 记录
    LintCode 1-30;
    Android在线程中发送GET和POST请求 在主线程更新UI
    Android中intent启动Activity中intent.setFlags()的作用
    源码备份 listview
    android数据库操作
    android 验证二
  • 原文地址:https://www.cnblogs.com/buringstraw/p/10589171.html
Copyright © 2011-2022 走看看