题目
题意:
有一个树形电网,要在某个节点建一个发电站,传输损耗是 I^2*Ri,Ri是总的电阻, 跟到各点距离总和有关。I是常数。
问最小的损耗,并输出最优的节点。
解法:
DFS两次统计每个点到其它点的距离总和即可。
Time:125ms Memory:5216KB Length: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 second using 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; }