题目大意:给定n个点坐标,m条有向边,要求最小树形图。
题解:直接上模板,前面打的 vis[v]=i一直把i打成1,一直TLE。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
const double inf=;
struct Point{
int x,y;
}p[];
struct Edge{
double w;
int u,v;
}e[];
int n,m;
double In[];
int pre[],id[],vis[];
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=;
int u,v,rt=;
while (){
for (int i=;i<n;i++) In[i]=inf;
for (int i=;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=;i<n;i++){
if (i==rt) continue;
if (fabs(In[i]-inf)<1e-) return -;
}
int cnt=;
memset(id,-,sizeof id);
memset(vis,-,sizeof vis);
In[rt]=;
for (int i=;i<n;i++){
ret+=In[i];
v=i;
while (v!=rt&&vis[v]!=i&&id[v]==-){
vis[v]=i;
v=pre[v];
}
if (v!=rt&&id[v]==-){
for (u=pre[v];u!=v;u=pre[u]){
id[u]=cnt;
}
id[v]=cnt++;
}
}
if (cnt==) break;
for (int i=;i<n;i++){
if (id[i]==-) id[i]=cnt++;
}
for (int i=;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=;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y);
for (int i=;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);
}
}
黄维大沙茶