标签:最短路 注意 长度 并查集 hdu 计算 return text 相等
Description
Input
Output
Sample Input 1 4 6 1 2 1 2 3 2 3 4 3 4 1 4 1 3 5 2 4 6 Sample Output 6 3.33
/* 3 0 0 3 3 1 2 1 2 3 2 1 3 5 4 6 1 2 1 2 3 2 3 4 3 4 1 4 1 3 5 2 4 6 */ #include<cstdio> #include<algorithm> #include<vector> #include<iostream> #include<string.h> using namespace std; vector<pair<int,int> > v[100010]; struct Edge { int f,t,q; }; int m,n;//n为村庄数,m为街道数 Edge s[1000010];//存储图 long long ans;//存最后的每条路的总和 int pre[100010];//并查集的祖先数组 int vis[100010];//标记数组 bool cmp(Edge a,Edge b )//排序函数 { return a.q<b.q; } int Find(int x)//找祖先 { if(x!=pre[x]) { pre[x]=Find(pre[x]); } return pre[x]; } void Merge(int x,int y)//查是否相等 { int fx=Find(x); int fy=Find(y); if(fx!=fy) pre[fx]=fy; } long long dfs(int x) //dfs递归搜索 { vis[x]=1; long long now=0,all=1;//now记录当前节点直接连接的节点数量 all记录此节点经过搜索后所有的与此节点连接的节点数 int h=v[x].size(); for(int i=0; i<h; i++) { int b=v[x][i].first; if(!vis[b]) { now=dfs(b); all+=now; ans+=now*(n-now)*v[x][i].second;//ans记录的是权值*经过的次数 } } return all; } int main() { int t; scanf("%d",&t); while(t--) { ans=0; memset(vis,0,sizeof(vis)); scanf("%d%d",&n,&m); if(m==0||n==0) {printf("0 0.00");continue;} for(int i=0;i<=n;i++) v[i].clear(); for(int i=0; i<=n; i++)//并查集的祖先节点的初始化 { pre[i]=i; } for(int j=0; j<m; j++)//输入 { scanf("%d%d%d",&s[j].f,&s[j].t,&s[j].q); } sort(s,s+m,cmp);//排序 long long sum=0;//sum用来记录最小生成树的长度 for(int j=0; j<m; j++) { int fx=Find(s[j].f); int fy=Find(s[j].t); if(fx!=fy) //如果祖先不相等,那么加入到最小生成树中 { sum=sum+s[j].q; Merge(fx,fy); //加入到动态数组中准备做期望 v[s[j].f].push_back(make_pair(s[j].t,s[j].q)); v[s[j].t].push_back(make_pair(s[j].f,s[j]. q)); } } dfs(1);//深搜回溯计算ans的值 double y=1.0*n*(n-1)/2; printf("%lld %.2lf\n",sum,(double)ans/y); } return 0; }
HDU5723 Abandoned country 最小生成树+深搜回溯法
标签:最短路 注意 长度 并查集 hdu 计算 return text 相等
原文地址:http://www.cnblogs.com/aiguona/p/7214707.html