您的位置:首页 > 其它

POJ-3164- Command Network(最小树形图)

2017-02-21 14:38 387 查看
题目链接:POJ-3164- Command Network

最小树形图的算法:

1. 找出除根之外每个点的
in[i]
in[i]
表示点i所有入边的最小值。

2. 检测图中是否有环,若无环,则已经找到最小树形图。若有环,则将环染色缩点,若u与v在同一个环中,中,那么 id[u]==id[v] 。

3. 缩点,对于边 (u,v,d) ,将其转化为 (id[u],id[v],d−in[v]) 。

4. 重复上面三步,每一步res+=除根之外所有的
in[i]


为什么新入边权值要减去
in[v]


在每一步由所有的
in[i]
生成的图中,若存在环,则必然没有没有边指向这个环。要让这个环消失,则必然要在这个环中删去一边,并在这个环外选取一边指向环,假设我们选取一个指向 u 的边作为新边,则必然要删去
in[u]
,因此将所有指向 u 的边减去
in[u]
,这样在之后的步骤中,选取了新边,则自然删去了环中对应的边。

具体可以看最小树形图

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mp make_pair
#define pr pair<int,int>
#define fi fisr
using namespace std;
typedef long long ll;
const double INF=1e10;
struct Edge
{
int u,v;
double d;
};
int n,m;
int vis[107],id[107],pre[107];
Edge edges[10007];
double in[107],x[107],y[107];
double zhuliu(int rt)
{
double res=0;
while(1)
{
//1.找最小入边
for(int i=1;i<=n;i++)
in[i]=INF;
for(int i=0;i<m;i++)
{
int u=edges[i].u,v=edges[i].v;
if(edges[i].d<in[v]&&u!=v)  //忽略重边,因为重边不影响最小树形图
in[v]=edges[i].d,pre[v]=u;
}
for(int i=1;i<=n;i++)
if(i!=rt&&in[i]==INF)   //若一点与图不连通,则不存在最小树形图
return INF;
//2.找环
int tn=0;
memset(vis,-1,sizeof(vis));
memset(id,-1,sizeof(id));
in[rt]=0;
for(int i=1;i<=n;i++)
{
res+=in[i];
int u=i;
//找环
while(u!=rt&&id[u]==-1&&vis[u]!=i)
{
vis[u]=i;
u=pre[u];
}
//染色
if(u!=rt&&id[u]==-1)
{
id[u]=++tn;
for(int v=pre[u];v!=u;v=pre[v]) id[v]=tn;
}
}
if(tn==0)   break;  //不发现环,则是最小树形图,返回
//将不在环中的点染色
for(int i=1;i<=n;i++)   if(id[i]==-1)   id[i]=++tn;
//3.缩点
for(int i=0;i<m;)
{
int u=edges[i].u,v=edges[i].v;
edges[i].u=id[u];
edges[i].v=id[v];
if(edges[i].u!=edges[i].v)
edges[i++].d-=in[v];
else edges[i]=edges[--m];
}
n=tn;
rt=id[rt];

f923
}
return res;
}

int main()
{
while(~scanf("%d%d",&n,&m))
{
int u,v;
for(int i=1;i<=n;i++)   scanf("%lf%lf",&x[i],&y[i]);
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
edges[i].u=u;edges[i].v=v;
edges[i].d=sqrt(pow(x[u]-x[v],2)+pow(y[u]-y[v],2));
}
double ans=zhuliu(1);
if(ans==INF) puts("poor snoopy");
else printf("%.2f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: