hdu 2489 hdu1598 依旧最小生成树
hdu2489
求一个图中的一颗子树,使得Sum(edge weight)/Sum(point weight)最小~
数据量很小,暴力枚举,只是要注意精度,否则WA~
dfs暴力枚举C(M,N)种情况。
枚举出这M个点之后,Sum(point weight)固定,进行prime或者Kruskal使Sum(edge weight)求最小。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <math.h> 2 #include <stdio.h> 3 #include <string.h> 4 const int N=20; 5 const int inf=10000000; 6 int w[N];//用于记录每个点的权值 7 int ans[N];//用于记录答案点 8 int node[N];//用于记录临时的枚举的m个点 9 int map[N][N],f[N][N]; 10 int n,m; 11 double res; 12 int vis[N*(N+1)/2];//用于prime算法 13 int dis[N*(N+1)/2];//用于prime算法 14 int Prime(){ 15 int i,j,t; 16 memset(vis,0,sizeof(vis)); 17 for(i=1;i<=m;i++){ 18 if(i==1) dis[i]=0; 19 else dis[i]=map[1][i]; 20 } 21 int loc,sum=0; 22 for(i=1;i<=m;i++){ 23 int min=inf; 24 for(j=1;j<=m;j++){ 25 if(!vis[j]&&dis[j]<min){ 26 min=dis[j]; 27 loc=j; 28 } 29 } 30 vis[loc]=1; 31 sum+=min; 32 for(j=1;j<=m;j++){ 33 if(!vis[j]&&map[loc][j]<dis[j]){ 34 dis[j]=map[loc][j]; 35 } 36 } 37 } 38 return sum; 39 } 40 void dfs(int u,int cnt){ 41 int i,j; 42 node[cnt]=u; 43 if(cnt>=m){ 44 for(i=1;i<=m;i++) 45 for(j=1;j<=m;j++) 46 map[i][j]=f[node[i]][node[j]]; 47 double sumEdge=1.0*Prime(); 48 double sumPoint=0; 49 for(i=1;i<=m;i++){ 50 sumPoint+=w[node[i]]; 51 } 52 double sum=sumEdge/sumPoint; 53 if(sum-res<-(1e-8)){ 54 res=sum; 55 for(i=1;i<=m;i++) 56 ans[i]=node[i]; 57 } 58 return ; 59 } 60 61 for(i=u+1;i<=n;i++) 62 dfs(i,cnt+1); 63 } 64 int main(){ 65 int i,j; 66 while(scanf("%d %d",&n,&m)!=EOF){ 67 if(n==0&&m==0) break; 68 for(i=1;i<=n;i++){ 69 scanf("%d",&w[i]); 70 } 71 for(i=1;i<=n;i++) 72 for(j=1;j<=n;j++) 73 scanf("%d",&f[i][j]); 74 75 res=inf; 76 for(i=1;i<=n;i++) 77 dfs(i,1); 78 79 for(i=1;i<m;i++) 80 printf("%d ",ans[i]); 81 printf("%d\n",ans[i]); 82 } 83 return 0; 84 }
hdu1598
最小生成树变形
给两个点求出从start到end的一条路径,满足权值最大的边-权值最小的边的差最小~
或者说是贪心+并查集吧:
思路如下:将所有的边按照权值大小排序,然后从第一条边开始枚举,每次枚举都按照kruskal寻找一直到start和end在一个集合里了,
就不用继续合并了,此时用最后加入的边-枚举的那条边,以此类推,找所有情况中的最小值。
依旧枚举~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <vector> 3 #include <string.h> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int N=205; 8 const int inf=100000000; 9 int n,m,q; 10 int start,end; 11 int father[N]; 12 struct edge{ 13 int x,y,z; 14 }e[N]; 15 int max(int a,int b){return a>b?a:b;} 16 int min(int a,int b){return a<b?a:b;} 17 int find(int x){ 18 if(father[x]!=x) 19 father[x]=find(father[x]); 20 return father[x]; 21 } 22 void merge(int a,int b){ 23 int x=find(a); 24 int y=find(b); 25 if(x!=y) 26 father[x]=y; 27 } 28 int cmp(edge e1,edge e2){ 29 return e1.z<e2.z; 30 } 31 void init(){ 32 int i; 33 for(i=0;i<=n;i++){ 34 father[i]=i; 35 } 36 } 37 int main(){ 38 int i,j; 39 while(scanf("%d %d",&n,&m)!=EOF){ 40 for(i=0;i<m;i++){ 41 scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].z); 42 } 43 sort(e,e+m,cmp); 44 scanf("%d",&q); 45 while(q--){ 46 int _min=inf,res; 47 scanf("%d %d",&start,&end); 48 for(i=0;i<m;i++){ 49 init(); 50 res=inf; 51 for(j=i;j<m;j++){ 52 merge(e[j].x,e[j].y); 53 if(find(start)==find(end)){ 54 res=e[j].z-e[i].z; 55 } 56 } 57 _min=min(res,_min); 58 } 59 if(_min==inf) _min=-1; 60 printf("%d\n",_min); 61 } 62 } 63 return 0; 64 }