XMU1344建食堂

来源:互联网 发布:滴滴大数据平台 成都 编辑:程序博客网 时间:2024/04/27 18:27

http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1344


厦门大学在翔安也有了个新校区,新校区有n栋宿舍楼。由于地处偏僻,道路有限,只有n-1条路,每条路都是双向的,连接两栋宿舍楼,任意两栋楼都有且仅有一条路径互相到达。开发商想在校区内建一座食堂,食堂不能建在道路上,必须是在某栋宿舍楼。由于食堂实在很好吃,所有学生都会走路来这儿吃饭或买饭。为了便民,避免不必要的多走路,开发商希望食堂所在的宿舍楼到其他各个宿舍楼的距离之和最小,求这个最小值。


 经典问题。先建树,这里vector果然好用。g[i]保存点i所有子节点到i点的距离之和。s[i]保存以该点为根的树的节点数,然后

 f[x]=f[fa]+l[ln].l1*(n-2*s[x]);
DFS利用父节点得到的数据计算子节点的数据。
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<vector>#include<algorithm>#include<map>#include<cmath>using namespace std;#define M 1000000000#define N 10005struct line{    int a,b,l1;}l[2*N];vector<int> p[N],p2[N];int g[N],f[N],n,s[N];bool tp[N];int dfs1(int x){    tp[x]=false;    int ans=0;    unsigned int i;    bool h=false;    for (i=0;i<p2[x].size();i++)    {        int bb=l[p2[x][i]].b;        if (tp[bb]==true)        {            g[bb]=dfs1(bb);            ans+=g[bb]+l[p2[x][i]].l1*s[bb];            s[x]+=s[bb];            h=true;            p[x].push_back(p2[x][i]);        }    }    if (h==false) s[x]=1;    else s[x]+=1;    return ans;}void dfs2(int fa,int x,int ln){    tp[x]=false;    unsigned int i;    if (x!=1) f[x]=f[fa]+l[ln].l1*(n-2*s[x]);    for (i=0;i<p[x].size();i++)    dfs2(x,l[p[x][i]].b,p[x][i]);}int main(){    //freopen("a","r",stdin);    int i;    n=1;    scanf("%d",&n);    while(n!=0)    {        int h,k,ss;        for (i=1;i<=n;i++)        {            tp[i]=true;            s[i]=0;            p2[i].clear();            p[i].clear();        }        for (i=1;i<=n-1;i++)        {            scanf("%d%d%d",&h,&k,&ss);            p2[h].push_back(i);            l[i].a=h;            l[i].b=k;            l[i].l1=ss;            p2[k].push_back(i+n-1);            l[i+n-1].b=h;            l[i+n-1].a=k;            l[i+n-1].l1=ss;        }        g[1]=dfs1(1);        f[1]=g[1];        for (i=1;i<=n;i++) tp[i]=true;        tp[1]=false;        dfs2(0,1,0);        int ans=M;        for (i=1;i<=n;i++)        if (f[i]<ans) ans=f[i];        printf("%d\n",ans);        scanf("%d",&n);    }    return 0;}