zoukankan      html  css  js  c++  java
  • 【POJ】【3164】Commond Network

    最小树形图

      最小树形图模板题,朱-刘算法。

      题解:http://blog.csdn.net/shuangde800/article/details/8039359

      这位大神代码写的非常通俗易懂,而且这种代码风格也很值得学习……面向对象?= =听说这样封装起来可以避免using namespace std;出现的奇葩错误

    写错的地方:一开始找最小前驱边的时候 把 “!inc[i]"的叹号丢了……

      1 //POJ 3164
      2 #include<cmath>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<iostream>
      7 #include<algorithm>
      8 #define rep(i,n) for(int i=0;i<n;++i)
      9 #define F(i,j,n) for(int i=j;i<=n;++i)
     10 #define D(i,j,n) for(int i=j;i>=n;--i)
     11 using namespace std;
     12 void read(int &v){
     13     v=0; int sign=1; char ch=getchar();
     14     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     15     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     16     v*=sign;
     17 }
     18 /******************tamplate*********************/
     19 const int N=110;
     20 const int INF=~0u>>2;
     21 template<typename Type>
     22 class Directed_MST{
     23     public:
     24     void init(int _n){
     25         n=_n;
     26         ans=0;
     27         memset(vis,0,sizeof vis);
     28         memset(inc,0,sizeof inc);
     29         F(i,0,n){
     30             w[i][i]=INF;
     31             F(j,i+1,n) w[i][j]=w[j][i]=INF;
     32         }
     33     }
     34     void insert(int x,int y,Type _w){
     35         if (w[x][y]>_w) w[x][y]=_w;
     36     }
     37     Type directed_mst(int x){
     38 #ifdef debug
     39         F(i,1,n){
     40             F(j,1,n) 
     41                 if (w[i][j]==INF) printf(" INF ");
     42                 else printf("%.2f ",w[i][j]);
     43             printf("
    ");
     44         }
     45 #endif
     46         // step1 判断能否形成最小树形图,直接dfs遍历
     47         dfs(x);
     48         F(i,1,n) if(!vis[i]) return -1;
     49         
     50         // 如果可以形成最小树形图,继续
     51         // step2
     52         memset(vis,0,sizeof vis);
     53         while(1){
     54             //1.找最小前驱边
     55             F(i,1,n) if (i!=x && !inc[i]){
     56                 w[i][i]=INF, pre[i]=i;
     57                 F(j,1,n) 
     58                     if(!inc[j] && w[j][i]<w[pre[i]][i])
     59                         pre[i]=j;
     60             }
     61             //2.判断是否有环
     62             int i;
     63             for(i=1;i<=n;++i) if (i!=x && !inc[i]){
     64                 int j=i,cnt=0;
     65                 while(j!=x && pre[j]!=i && cnt<=n) j=pre[j],++cnt;
     66                 if (j==x || cnt>n) continue;
     67                 break;
     68             }
     69                 
     70             //没有找到环,找到答案
     71             if (i>n){
     72                 F(i,1,n)
     73                     if (i!=x && !inc[i]) ans+=w[pre[i]][i];
     74                 return ans;
     75             }
     76             //有环,进行收缩
     77             int j=i;
     78             memset(vis,0,sizeof vis);
     79             do{
     80                 ans+=w[pre[j]][j],j=pre[j],vis[j]=inc[j]=true;
     81             }while(j!=i);
     82             inc[i]=false;//!!!!环缩成了点i,点i依然存在
     83             
     84             //收缩
     85             F(k,1,n) if(vis[k])
     86                 F(j,1,n) if(!vis[j]){
     87                     if (w[i][j]>w[k][j]) w[i][j]=w[k][j];
     88                     if (w[j][k]<INF && w[j][k]-w[pre[k]][k] < w[j][i])
     89                         w[j][i]=w[j][k]-w[pre[k]][k];
     90                 }
     91         }
     92         return ans;
     93     }
     94 
     95     private:
     96     void dfs(int x){
     97         vis[x]=1;
     98         F(i,1,n) if (!vis[i] && w[x][i]<INF)
     99             dfs(i);
    100     }
    101     private:
    102     Type ans;
    103     int n;
    104     int pre[N];
    105     bool vis[N],inc[N];
    106     Type w[N][N];
    107 };
    108 struct node{
    109     double x,y;
    110     double operator - (const node&now)const{
    111         return sqrt( (x-now.x)*(x-now.x)+(y-now.y)*(y-now.y) );
    112     }
    113 }a[N];
    114 
    115 Directed_MST<double>G;
    116 
    117 int main(){
    118     int n,m,x,y;
    119     while(scanf("%d%d",&n,&m)!=EOF){
    120         G.init(n);
    121         F(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
    122         
    123         F(i,1,m){
    124             scanf("%d%d",&x,&y);
    125             if (x==y) continue;
    126             G.insert(x,y,a[x]-a[y]);
    127         }
    128         double ans=G.directed_mst(1);
    129         if (ans<0) puts("poor snoopy");
    130         else printf("%.2f
    ",ans);
    131     }
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    python实现简单爬虫功能
    python re group()
    [转载]python 详解re模块
    Python 异常处理
    Python中os和shutil模块实用方法集锦
    Python中os和shutil模块实用方法集锦
    关于selenium IDE找不到元素
    关于selenium IDE找不到元素
    关于selenium IDE找不到元素
    js模拟点击事件实现代码
  • 原文地址:https://www.cnblogs.com/Tunix/p/4245048.html
Copyright © 2011-2022 走看看