POJ3164 最小树形图

来源:互联网 发布:慢走丝统盈编程 编辑:程序博客网 时间:2024/06/07 20:36

才知道有向图还有最小生成树一说,磨磨蹭蹭搞了半天,范了个很SB的错误,改后总算是过了。。。


ACcode:

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const int NS=110;const double INF=1e9;struct Point{    double x,y;    void input(){        scanf("%lf %lf",&x,&y);    }}p[NS];struct Edge{    int u,v;    double w;    Edge(){}    Edge(int _u,int _v,double _w){        u=_u,v=_v,w=_w;    }}edge[NS*NS];int n,m;double dist(Point a,Point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int pre[NS],id[NS],vis[NS];double in[NS];double solve(int rt,int nv,int ne){    double ret=0.0;    while(true)    {        int cnt=0;        for (int i=0;i<nv;i++)            in[i]=INF,id[i]=vis[i]=-1;        memset(id,-1,sizeof(id));        memset(vis,-1,sizeof(vis));        for (int i=0;i<ne;i++)        {            int u=edge[i].u;            int v=edge[i].v;            double w=edge[i].w;            if (u!=v && v!=rt && w<in[v])            {                in[v]=w;                pre[v]=u;            }        }        for (int i=0;i<nv;i++)            if (i!=rt && in[i]==INF)                return (-1.0);        in[rt]=0.0;        for (int i=0;i<nv;i++)        {            ret+=in[i];            if (id[i]==-1)            {                int v=i;                while ( v!=rt && vis[v]!=i && id[v]==-1)                {                    vis[v]=i;                    v=pre[v];                }                if ( v!=rt && id[v]==-1 )                {                    for (int u=pre[v];u!=v;u=pre[u])                    {                        id[u]=cnt;                    }                    id[v]=cnt++;                }            }        }        if (!cnt) break;        for (int i=0;i<nv;i++)            if (id[i]==-1)                id[i]=cnt++;        for (int i=0;i<ne;i++)        {            int u=edge[i].u;            int v=edge[i].v;            edge[i].u=id[u];            edge[i].v=id[v];            if (id[u]!=id[v])            {                edge[i].w-=in[v];            }        }        nv=cnt;        rt=id[rt];    }    return ret;}int main(){    while (~scanf("%d%d",&n,&m))    {        for (int i=0;i<n;i++)            p[i].input();        for (int i=0;i<m;i++)        {            int u,v;            scanf("%d%d",&u,&v);            u--,v--;            double w=dist(p[u],p[v]);            if (u==v) w=INF;            edge[i]=Edge(u,v,w);        }        double ans=solve(0,n,m);        if (ans>=0.0)            printf("%.2f\n",ans);        else            printf("poor snoopy\n");    }    return 0;}