POJ 3164 Command Network(最小树形图模板)

来源:互联网 发布:深圳税友软件 编辑:程序博客网 时间:2024/05/29 08:59

大概题意:给出n个网络节点的个数和其坐标,然后m条单向边,服务器的位置是1,问要是所有的基站都受到信号,最小的花费是多少...

有向图的最小生成树,是最小树形图,要用到朱刘算法去做...在学长博客扒到一份模板,果断用之,套上就AC了...不是难题...

模板链接:点击打开链接

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<iostream>using namespace std;#define inf 1<<30struct node{    int u,v;    double w;}edge[20000];int pre[200],id[200],use[200];double in[200];double dis(int x1,int y1,int x2,int y2){    return sqrt(0.0+(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}double mini_tree(int root,int n,int m){    double ans=0;    int i,u;    while(1)    {        for(i=1;i<=n;i++)            in[i]=inf;        for(i=1;i<=m;i++)        {            int u=edge[i].u;            int v=edge[i].v;            if(edge[i].w<in[v]&&u!=v)            {                in[v]=edge[i].w;                pre[v]=u;            }        }        for(i=1;i<=n;i++)        {            if(i==root)continue;            ans+=in[i];            if(in[i]==inf)                return -1;        }        memset(id,-1,sizeof(id));        memset(use,-1,sizeof(use));        int cnt=0;        for(i=1;i<=n;i++)        {            int v=i;            while(v!=root&&use[v]!=i&&id[v]==-1)            {                use[v]=i;                v=pre[v];            }            if(v!=root&&id[v]==-1)            {                ++cnt;                id[v]=cnt;                for(u=pre[v];u!=v;u=pre[u])                    id[u]=cnt;            }        }        if(cnt==0)            break;        for(i=1;i<=n;i++)            if(id[i]==-1)                id[i]=++cnt;        for(i=1;i<=m;i++)        {            int u=edge[i].u;            int v=edge[i].v;            edge[i].u=id[u];            edge[i].v=id[v];            if(edge[i].u!=edge[i].v)                edge[i].w-=in[v];        }        n=cnt;        root=id[root];    }    return ans;}int main(){    int x[200],y[200],n,m;    while(cin>>n>>m)    {        int u,v;        for(int i=1;i<=n;i++)            scanf("%d %d",&x[i],&y[i]);        for(int i=1;i<=m;i++)        {            scanf("%d %d",&u,&v);            edge[i].u=u;            edge[i].v=v;            edge[i].w=dis(x[u],y[u],x[v],y[v]);        }        double ans=mini_tree(1,n,m);        if(ans<0)            printf("poor snoopy\n");        else            printf("%.2f\n",ans);    }    return 0;}


0 0
原创粉丝点击