POJ2377
题意:求最大生成树
分析:把边权值变成负值,最后取绝对值,注意最后的判断,如果生成树的边的数目小于(顶点数-1)则表示不能构成生成树
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <vector> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <bitset> 10 #include <cmath> 11 #include <queue> 12 #include <stack> 13 using namespace std; 14 const int maxn=20020; 15 int par[maxn],rankl[maxn]; 16 17 void init(int n) 18 { 19 for(int i=0;i<=n;i++) 20 { 21 par[i]=i; 22 rankl[i]=0; 23 } 24 } 25 int findl(int x) 26 { 27 if(par[x]==x) 28 return x; 29 else 30 return par[x]=findl(par[x]); 31 } 32 void unite(int x,int y) 33 { 34 x=findl(x); 35 y=findl(y); 36 if(x==y) return; 37 if(rankl[x]<rankl[y]){ 38 par[x]=y; 39 }else{ 40 par[y]=x; 41 if(rankl[x]==rankl[y]) rankl[x]++; 42 } 43 } 44 bool same(int x,int y) 45 { 46 return findl(x)==findl(y); 47 } 48 int n,m; 49 struct edge{ 50 int u,v,cost; 51 }; 52 bool cmp(const edge e1,const edge e2){ 53 return e1.cost<e2.cost; 54 } 55 edge es[maxn]; 56 int ans; 57 int kruskal() 58 { 59 sort(es,es+m+1,cmp); 60 init(n); 61 int res=0; 62 for(int i=0;i<m;i++){ 63 edge e=es[i]; 64 if(!same(e.u,e.v)){ 65 unite(e.u,e.v); 66 res+=e.cost; 67 ans++; 68 } 69 } 70 return res; 71 } 72 int main() 73 { 74 while(cin>>n>>m) 75 { 76 for(int i=0;i<m;i++) 77 { 78 int a,b,c; 79 scanf("%d%d%d",&a,&b,&c); 80 es[i].u=a,es[i].v=b,es[i].cost=-c; 81 } 82 ans=0; 83 int cnt=0-kruskal(); 84 // cout<<ans<<endl; 85 if(ans==n-1) 86 cout<<cnt<<endl; 87 else 88 cout<<"-1"<<endl; 89 } 90 return 0; 91 }
AOJ2224
题意:给定一个图,并给出每条边的一些信息,问要让这个图构成树,去掉的最小长度是多少
分析:因为求的是去掉的最小长度,所以剩下的必然是最大的,这就是一个最大生成树问题,注意一下输入问题,开始给定的是点的坐标,后面给定的是哪些点是联通的
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <vector> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <bitset> 10 #include <cmath> 11 #include <queue> 12 #include <stack> 13 using namespace std; 14 const int maxn=10100; 15 const int maxm=10000*10000/2; 16 int par[maxn],rankl[maxn]; 17 18 //并查集 19 void init(int n) 20 { 21 for(int i=0;i<=n;i++) 22 { 23 par[i]=i; 24 rankl[i]=0; 25 } 26 } 27 int findl(int x) 28 { 29 if(par[x]==x) 30 return x; 31 else 32 return par[x]=findl(par[x]); 33 } 34 void unite(int x,int y) 35 { 36 x=findl(x); 37 y=findl(y); 38 if(x==y) return; 39 if(rankl[x]<rankl[y]){ 40 par[x]=y; 41 }else 42 { 43 par[y]=x; 44 if(rankl[x]==rankl[y]) rankl[x]++; 45 } 46 } 47 bool same(int x,int y) 48 { 49 return findl(x)==findl(y); 50 } 51 struct edge{ 52 int u,v; 53 double cost; 54 }; 55 bool cmp(const edge e1,const edge e2) 56 { 57 return e1.cost<e2.cost; 58 } 59 edge es[maxm]; 60 int n,m; 61 double kruskal() 62 { 63 sort(es+1,es+m+1,cmp); 64 init(n); 65 double res=0; 66 for(int i=1;i<=m;i++){ 67 edge e=es[i]; 68 if(!same(e.u,e.v)){ 69 unite(e.u,e.v); 70 res+=e.cost; 71 } 72 } 73 return res; 74 } 75 double a[maxn],b[maxn]; 76 struct app 77 { 78 int x,y; 79 }; 80 app s[maxm]; 81 double distance(double x1,double y1,double x2,double y2) 82 { 83 double t1=(x1-x2)*(x1-x2); 84 double t2=(y1-y2)*(y1-y2); 85 return sqrt(t1+t2); 86 } 87 int main() 88 { 89 while(cin>>n>>m) 90 { 91 memset(a,0,sizeof(a)); 92 memset(b,9,sizeof(b)); 93 for(int i=1;i<=n;i++) //输入点的坐标 94 { 95 scanf("%lf%lf",&a[i],&b[i]); 96 } 97 double hh=0.0; 98 for(int i=1;i<=m;i++) //输入有边的点 99 { 100 scanf("%d%d",&s[i].x,&s[i].y); 101 int x=s[i].x,y=s[i].y; 102 es[i].u=x,es[i].v=y; 103 es[i].cost=-distance(a[x],b[x],a[y],b[y]); 104 hh+=-es[i].cost; 105 } 106 double tt=0-kruskal(); 107 printf("%.3lf ",hh-tt); 108 } 109 return 0; 110 }