poj 3164 <朱刘算法《模板》求最小树形图>

来源:互联网 发布:东阳市农村淘宝分布 编辑:程序博客网 时间:2024/05/30 22:44

题目链接:  poj 3164


有向图的最小树形图:此算法由朱永津和刘振宏在1965年发表。

膜拜--

写下自己理解的思路---    一天一道题----痛并快乐着--

解题步骤:

1》先从根节点DFS一下,看是否有解--

2》寻找除根节点外的所有点的最小入边--

3》从所有点向上寻找--看中间路径是否存在环--(如果不存在环,说明已经找到最小树形图--将各边加入ans中--算法结束)

4》如果存在环的话就先将环上各边之和加入ans--然后找各点的其他入边并更新(因为已将最小入边加上--其他入边以后如果还用时就应该用它与最小入边的差值)

---然后-收缩环为环中一点--除收缩点外,其他点与外界的状态全部转移到收缩点--其他点标记一下(隐藏)--然后返回步骤2.


图文可在百度文库下载:最小树形图



代码:

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm> using namespace std;int n,m;#define M 999999999double x[120],y[120];double map[120][120];bool fafe[120];double dist(int xx,int yy){double lp=sqrt((x[xx]-x[yy])*(x[xx]-x[yy])+(y[xx]-y[yy])*(y[xx]-y[yy]));return lp;}int fer[120];double zhuliu(){int pre[120],i;bool visit[120]; double ans=0;for (int i=1;i<=n;i++){fafe[i]=false;map[i][i]=M;}pre[1]=1;while (true){for (i=2;i<=n;i++){if (fafe[i])continue;pre[i]=i;for (int j=1;j<=n;j++){if (!fafe[j]&&map[j][i]<map[pre[i]][i])pre[i]=j;}}for (i=2;i<=n;i++){if (fafe[i])continue;memset(visit,false,sizeof(visit));visit[1]=true;int j=i;do{visit[j]=true;j=pre[j];}while(!visit[j]);if (j==1) continue;//从根节点出发--到i之间无环。i=j;/*这里是i=j,,,写成j=i就超时--- 如果有环时j不是回到i了吗?? 原来是从i想上找---循环可能没有i---如:3——4---5----4:pre[3]=4--pre[4]=5---pre[5]=4;这样的话--如果下面的循环还是从i开始--但是判断结果是就j!=i--永远会不到3的位置--就会 Time Limit Exceeded*/do{ans+=map[pre[j]][j];j=pre[j];}while (j!=i);j=i;do//改变权值 {for (int k=1;k<=n;k++){if (fafe[k]) continue;if (map[k][j]<M&&k!=pre[j])map[k][j]-=map[pre[j]][j];}j=pre[j];}while (j!=i);for (j=1;j<=n;j++)//将与环上的点相连的路全部连在i上 {if (j==i) continue;for (int k=pre[i];k!=i;k=pre[k]){if (map[k][j]<map[i][j]) map[i][j]=map[k][j];if (map[j][k]<map[j][i]) map[j][i]=map[j][k];}}for (j=pre[i];j!=i;j=pre[j])//除i点,其他点隐藏 fafe[j]=true;break;// 此环已压缩--当做一点--重新找每点的最短入边-- }if (i==n+1)//从2到n都无环--- {for (int j=2;j<=n;j++)if (!fafe[j])ans+=map[pre[j]][j];break;}}return ans;}void DFS(int xx){fafe[xx]=false;for (int i=1;i<=n;i++)if (fafe[i]&&map[xx][i]!=M)DFS(i);return ;}int main(){while (~scanf("%d%d",&n,&m)){for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)map[i][j]=M;for (int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);int a,b;for (int i=0;i<m;i++){scanf("%d%d",&a,&b);if (a==b) continue;map[a][b]=dist(a,b);}bool falg=true;memset(fafe,true,sizeof(fafe));DFS(1);for (int i=1;i<=n;i++)if (fafe[i]){falg=false;break;}if (falg)printf("%.2lf\n",zhuliu());elseprintf("poor snoopy\n");}return 0;}


0 0