您的位置:首页 > 其它

POJ 3164 Command Network(最小树形图)

2013-01-05 23:26 465 查看
题目链接:http://poj.org/problem?id=3164

题意:给定一个图,求最小树形图。1为根节点。

思路:求以root为根的最小树形图(假设图中每个点均可由root到达):

(1)为每个顶点找一条权值最小的入边;

(2)此时如不存在环,结束;否则转(3);

(3)将环缩成一个点new;对于环中的每个点u,环中u的入边权值为x,对于边<u,i,dis>(i不在环中),增加边<new,i,dis>;对于边<i,u,dis>(i不在环中),增加边<i,new,dis-x>(显然你选择了这条边那么之前指向u的边就会删掉)。

(4)重复(1)到(3)直到结束。

#include <iostream>
#include <cmath>
#include <stdio.h>
#include <string.h>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;

struct Point
{
int x,y;
};

const double INF=1000000000.0;
Point p[105];
double map[105][105],ans;
int n,m,father[105],visit[105],flag[105];

double Dis(Point a,Point b)
{
return sqrt(0.0+(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

void DFS(int u)
{
int v;
visit[u]=1;
for(v=1;v<=n;v++) if(!visit[v]&&map[u][v]<INF) DFS(v);
}

int connet()
{
memset(visit,0,sizeof(visit));
DFS(1);
for(int i=1;i<=n;i++) if(!visit[i]) return 0;
return 1;
}

int exist_circle()
{
int i,j;

father[1]=1;
for(i=2;i<=n;i++) if(!flag[i])
{
father[i]=i;
map[i][i]=INF;
for(j=1;j<=n;j++) if(!flag[j]&&map[j][i]<map[father[i]][i])
father[i]=j;
}
for(i=2;i<=n;i++) if(!flag[i])
{
for(j=1;j<=n;j++) visit[j]=0;
for(j=i;!visit[j];j=father[j]) visit[j]=1;
if(j!=1) return j;
}
return -1;
}

void update(int t)
{
int i,j;

ans+=map[father[t]][t];
for(i=father[t];i!=t;i=father[i])
{
ans+=map[father[i]][i];
flag[i]=1;
}
for(i=1;i<=n;i++) if(!flag[i]&&map[i][t]<INF)
map[i][t]-=map[father[t]][t];
for(i=father[t];i!=t;i=father[i]) for(j=1;j<=n;j++) if(!flag[j])
{
if(map[j][i]<INF) map[j][t]=min(map[j][t],map[j][i]-map[father[i]][i]);
map[t][j]=min(map[t][j],map[i][j]);
}
}

double solve()
{
int i;
memset(flag,0,sizeof(flag));
ans=0.0;
while((i=exist_circle())!=-1) update(i);
for(i=2;i<=n;i++) if(!flag[i]) ans+=map[father[i]][i];
return ans;
}

int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j,u,v;
for(i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);
for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=INF;
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
map[u][v]=Dis(p[u],p[v]);
}
if(!connet()) puts("poor snoopy");
else printf("%.2lf\n",solve());
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: