POJ 4045 Power Station 解题报告

来源:互联网 发布:sql查询字段是否相等 编辑:程序博客网 时间:2024/04/29 06:19

题目


题意:

有一个树形电网,要在某个节点建一个发电站,传输损耗是 I^2*Ri,Ri是总的电阻, 跟到各点距离总和有关。I是常数。

问最小的损耗,并输出最优的节点。

解法:

DFS两次统计每个点到其它点的距离总和即可。

Time:125msMemory:5216KBLength:2039B#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <string>#include <vector>#include <map>#include <queue>#include <set>#include <sstream>#define DBLE 1e-8#define PI 3.1415926535898#define INF (100000000000LL)#define MAXN 100010#define MP(x,y) (make_pair((x),(y)))#define FI first#define SE secondusing namespace std;int he[MAXN],to[MAXN],nex[MAXN],top,node[MAXN];long long num[MAXN],ans;vector<int> vec;void add(int a,int b){    nex[top]=he[a];    to[top]=b;    he[a]=top++;}pair<int,int> dfs1(int h,int fa){    node[h]=1;    pair<int,int> pa;    for(int i=he[h];i!=-1;i=nex[i])        if(to[i]!=fa)        {            pa=dfs1(to[i],h);            node[h]+=pa.FI;            num[h]+=pa.SE+pa.FI;        }    return MP(node[h],num[h]);}void dfs2(int h,int fa,pair<int,int> pa){    pair<int,int> tpa=pa,ttpa;    num[h]+=pa.SE+pa.FI;    if(num[h]<=ans)    {        if(num[h]<ans)  ans=num[h],vec.clear();        vec.push_back(h);    }    tpa.SE+=tpa.FI,++tpa.FI;    for(int i=he[h];i!=-1;i=nex[i])        if(to[i]!=fa)            tpa.FI+=node[to[i]],tpa.SE+=num[to[i]]+node[to[i]];    for(int i=he[h];i!=-1;i=nex[i])        if(to[i]!=fa)        {            ttpa=tpa;            ttpa.FI-=node[to[i]],ttpa.SE-=num[to[i]]+node[to[i]];            dfs2(to[i],h,ttpa);        }}int main(){    //freopen("J:\\MyDocument\\Code\\input.txt","r",stdin);    int ncase,n,I,r,a,b;    scanf("%d",&ncase);    while(ncase--)    {        scanf("%d%d%d",&n,&I,&r);        memset(he,-1,sizeof(he));        memset(num,0,sizeof(num));        top=0;        for(int i=1;i<n;++i)            scanf("%d%d",&a,&b),add(a,b),add(b,a);        ans=INF;        vec.clear();        dfs1(1,-1);        dfs2(1,-1,MP(0,0));        cout<<(long long)ans*r*I*I<<'\n';        sort(vec.begin(),vec.end());        for(int i=0;i<vec.size();++i)            printf("%s%d",i?" ":"",vec[i]);        printf("\n\n");    }    return 0;}