大概题意:给出n个网络节点的个数和其坐标,然后m条单向边,服务器的位置是1,问要是所有的基站都受到信号,最小的花费是多少...
有向图的最小生成树,是最小树形图,要用到朱刘算法去做...在学长博客扒到一份模板,果断用之,套上就AC了...不是难题...
模板链接:点击打开链接
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define inf 1<<30
struct 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;
}