您的位置:首页 > 其它

poj3164 (朱刘算法 最小树形图)

2016-03-11 17:10 274 查看
题目大意:给定n个点坐标,m条有向边,要求最小树形图。

题解:直接上模板,前面打的 vis[v]=i一直把i打成1,一直TLE。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
const double inf=200000000;
struct Point{
int x,y;
}p[200005];
struct Edge{
double w;
int u,v;
}e[200005];
int n,m;
double In[200005];
int pre[200005],id[105],vis[105];
double dis(int i,int j){
return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
double zhuliu(){
double ret=0;
int u,v,rt=0;
while (1){
for (int i=0;i<n;i++) In[i]=inf;
for (int i=0;i<m;i++){
u=e[i].u;
v=e[i].v;
if (e[i].w<In[v]&&u!=v){
In[v]=e[i].w;
pre[v]=u;
}
}
for (int i=0;i<n;i++){
if (i==rt) continue;
if (fabs(In[i]-inf)<1e-8) return -1;
}
int cnt=0;
memset(id,-1,sizeof id);
memset(vis,-1,sizeof vis);
In[rt]=0;
for (int i=0;i<n;i++){
ret+=In[i];
v=i;
while (v!=rt&&vis[v]!=i&&id[v]==-1){
vis[v]=i;
v=pre[v];
}
if (v!=rt&&id[v]==-1){
for (u=pre[v];u!=v;u=pre[u]){
id[u]=cnt;
}
id[v]=cnt++;
}
}
if (cnt==0) break;
for (int i=0;i<n;i++){
if (id[i]==-1) id[i]=cnt++;
}
for (int i=0;i<m;i++){
u=e[i].u;
v=e[i].v;
e[i].u=id[u];
e[i].v=id[v];
if (e[i].u!=e[i].v){
e[i].w-=In[v];
}
}
n=cnt;
rt=id[rt];
}
return ret;
}
int main(){
freopen("poj3164.in","r",stdin);
freopen("poj3164.out","w",stdout);
while (~scanf("%d%d",&n,&m)){
for (int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y);
for (int i=0;i<m;i++){
scanf("%d%d",&e[i].u,&e[i].v);
e[i].u--;e[i].v--;
if (e[i].u==e[i].v) e[i].w=inf;
else
e[i].w=dis(e[i].u,e[i].v);
}
double t=zhuliu();
if (t<0.0) printf("poor snoopy\n");
else printf("%.2f\n",t);
}
}


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