有向图中点点连通边权之和最小
算法过程不研究了,以后能看懂再说。。
直接贴一道以前写过的题
Openjudge的题面是地震之后,实则为一道POJ题目
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int maxn = 105; 7 const int INF = 0x7fffffff; 8 template<typename Type> 9 struct Directed_MST 10 { 11 void init(int _n) 12 { 13 n=_n; 14 ans = 0; 15 memset(vis, 0, sizeof(vis)); 16 memset(inc, 0, sizeof(inc)); 17 for(int i=0; i<=n; ++i) 18 { 19 w[i][i] = INF; 20 for(int j=i+1; j<=n; ++j) 21 w[i][j]=w[j][i]=INF; 22 } 23 } 24 void insert(int u, int v, Type _w) 25 { 26 if(w[u][v]>_w) w[u][v] = _w; 27 } 28 Type directed_mst(int u) 29 { 30 dfs(u); 31 for(int i=1; i<=n; ++i) 32 if(!vis[i]) { return -1; } 33 memset(vis, 0, sizeof(vis)); 34 while(true) 35 { 36 for(int i=1; i<=n; ++i)if(i!=u&&!inc[i]) 37 { 38 w[i][i]=INF, pre[i] = i; 39 for(int j=1; j<=n; ++j)if(!inc[j] && w[j][i]<w[pre[i]][i]) 40 { 41 pre[i] = j; 42 } 43 } 44 int i; 45 for(i=1; i<=n; ++i)if(i!=u&&!inc[i]) 46 { 47 int j=i, cnt=0; 48 while(j!=u && pre[j]!=i && cnt<=n) j=pre[j], ++cnt; 49 if(j==u || cnt>n) continue; 50 break; 51 } 52 if(i>n) 53 { 54 for(int i=1; i<=n; ++i)if(i!=u && !inc[i]) ans+=w[pre[i]][i]; 55 return ans; 56 } 57 int j=i; 58 memset(vis, 0, sizeof(vis)); 59 do{ 60 ans += w[pre[j]][j], j=pre[j], vis[j]=inc[j]=true; 61 }while(j!=i); 62 inc[i] = false; 63 for(int k=1; k<=n; ++k)if(vis[k]) 64 { 65 for(int j=1; j<=n; ++j)if(!vis[j]) 66 { 67 if(w[i][j] > w[k][j]) w[i][j] = w[k][j]; 68 if(w[j][k]<INF && w[j][k]-w[pre[k]][k] < w[j][i]) 69 w[j][i] = w[j][k] - w[pre[k]][k]; 70 } 71 } 72 } 73 return ans; 74 } 75 void dfs(int u) 76 { 77 vis[u] = true; 78 for(int i=1; i<=n; ++i)if(!vis[i]&&w[u][i]<INF) 79 { 80 dfs(i); 81 } 82 } 83 Type ans; 84 int n; 85 int pre[maxn]; 86 bool vis[maxn]; 87 bool inc[maxn]; 88 Type w[maxn][maxn]; 89 }; 90 Directed_MST<double>G; 91 double x[maxn],y[maxn]; 92 double getDist(double x1,double y1,double x2,double y2 93 ) 94 { 95 return sqrt(pow(x1-x2,2)+pow(y1-y2,2)); 96 } 97 98 int main() 99 { 100 int n,m; 101 while(~scanf("%d%d",&n,&m)) 102 { 103 G.init(n); 104 for(int i=1; i<=n; ++i) 105 scanf("%lf%lf",&x[i],&y[i]); 106 for(int i=0; i<m; ++i) 107 { 108 int a,b; 109 scanf("%d%d",&a,&b); 110 if(a==b)continue; 111 G.insert(a,b,getDist(x[a],y[a],x[b],y[b])); 112 } 113 double ans = G.directed_mst(1); 114 if(ans < 0) puts("NO"); 115 else printf("%.2f ", ans); 116 } 117 return 0; 118 }
裸的最小树形图