#include<iostream>#include<algorithm>usingnamespace std;constint MAXN =200;int set[MAXN];structEdge{int x,y,z;}edge[MAXN];intFind_set(int x){if(x != set[x]) set[x]=Find_set(set[x]);return set[x];}voidKruskal(int num,int m){int ans =0;int tot =0;for(int i=0;i<num;i++){
set[i]= i;}for(int i=0;i<m;i++){int x =Find_set(edge[i].x);int y =Find_set(edge[i].y);if(x == y)continue;
set[x]= set[y];
tot++;
ans += edge[i].z;if(tot == num-1)break;}
cout<<ans<<endl;}boolcmp(Edge x,Edge y){return x.z<y.z;}intmain(){int n,m;char c,cc;while(cin>>n&&n){int num =0;for(int i=1;i<n;i++){
cin>>c>>m;for(int j=0;j<m;j++){
edge[num].x = c-'A';
cin>>cc;
edge[num].y = cc-'A';
cin>>edge[num].z;
num++;}}sort(edge,edge+num,cmp);Kruskal(n,num);}return0;}
2. poj 1287 Networking
水题
#include<iostream>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<vector>#include<cmath>#include<cstdio>#include<map>#include<iomanip>usingnamespace std;typedeflonglong ll;constint MAXN =2e5+100;constint INF =0x3f3f3f3f;int s[MAXN];structEdge{int u, v, w;booloperator<(const Edge &B)const{return w < B.w;}}edge[MAXN];intFIND(int x){return x == s[x]? x : s[x]=FIND(s[x]);}intKruskal(int n,int m){int ans =0;int num =0;for(int i=0;i<m;i++){int u = edge[i].u;int v = edge[i].v;
u =FIND(u);
v =FIND(v);if(u == v)continue;
s[u]= v;
num +=1;
ans += edge[i].w;if(num == n -1)break;}return ans;}intmain(){#ifdefLOCALfreopen("input.txt","r",stdin);freopen("output.txt","w",stdout);#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int n, m;while(cin >> n){if(n ==0)break;for(int i=1;i<=n;i++) s[i]= i;
cin >> m;for(int i=0;i<m;i++){
cin >> edge[i].u >> edge[i].v >> edge[i].w;}sort(edge, edge + m);
cout <<Kruskal(n, m)<<'\n';}return0;}
3. poj 2301 Building a Space Station
三维最小生成树,水题
#include<iostream>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<vector>#include<cmath>#include<cstdio>#include<map>#include<iomanip>usingnamespace std;typedeflonglong ll;constint MAXN =300;constint INF =0x3f3f3f3f;constdouble eps =1e-8;structPoint{double x, y, z;double r;}pt[MAXN];intdcmp(double x){if(fabs(x)< eps)return0;return x <0?-1:1;}structLine{int x, y;double dis;booloperator<(const Line &B)const{returndcmp(dis - B.dis)<0;}}le[30000];int s[MAXN];intFIND(int x){return x == s[x]? x : s[x]=FIND(s[x]);}doublekruskal(int n,int m){double ans =0;int num =0;for(int i=0;i<m;i++){int x =FIND(le[i].x);int y =FIND(le[i].y);if(x == y)continue;
num +=1;
s[x]= y;
ans += le[i].dis;if(num == n -1)break;}return ans;}intmain(){#ifdefLOCALfreopen("input.txt","r",stdin);freopen("output.txt","w",stdout);#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int n;while(cin >> n && n){for(int i=1;i<=n;i++) s[i]= i;for(int i=1;i<=n;i++){
cin >> pt[i].x >> pt[i].y >> pt[i].z >> pt[i].r;}int m =0;for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){
le[m].dis =sqrt(pow(pt[i].x - pt[j].x,2)+pow(pt[i].y - pt[j].y,2)+pow(pt[i].z - pt[j].z,2));
le[m].dis =max(0.0, le[m].dis - pt[i].r - pt[j].r);
le[m].x = i;
le[m].y = j;
m +=1;}}sort(le, le + m);for(int i=0;i<m;i++){// cout << le[i].x << ' ' << le[i].y << ' ' << le[i].dis << '\n';}
cout << fixed <<setprecision(3)<<kruskal(n, m)<<'\n';}return0;}
4. poj 2421 Constructing Roads
给定一些树上路径,让补全最小生成树,水题
#include<iostream>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<vector>#include<cmath>#include<cstdio>#include<map>#include<iomanip>usingnamespace std;typedeflonglong ll;constint MAXN =111;constint INF =0x3f3f3f3f;structst{int x, y;int dis;booloperator<(const st &B)const{return dis < B.dis;}}pt[MAXN * MAXN];int s[MAXN];intFIND(int x){return x == s[x]? x : s[x]=FIND(s[x]);}int num =0;intkruskal(int n,int m){int ans =0;if(num >= n -1)return0;for(int i=0;i<m;i++){int x =FIND(pt[i].x);int y =FIND(pt[i].y);if(x == y)continue;
s[x]= y;
ans += pt[i].dis;
num +=1;if(num == n -1)break;}return ans;}intmain(){#ifdefLOCALfreopen("input.txt","r",stdin);freopen("output.txt","w",stdout);#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int n;int q;
cin >> n;for(int i=1;i<=n;i++) s[i]= i;int m =0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){
cin >> pt[m].dis;if(i == j)continue;
pt[m].x = i;
pt[m].y = j;
m +=1;}}sort(pt, pt + m);
cin >> q;while(q--){int u, v;
cin >> u >> v;
u =FIND(u);
v =FIND(v);if(u == v)continue;
num +=1;
s[u]= v;}
cout <<kruskal(n, m);return0;}
5. zoj 1610 QS Network
给出点权边权,求最小生成树,水题
#include<bits/stdc++.h>usingnamespace std;structst{int x, y;int dis;};intmain(){
ios::sync_with_stdio(false);
cin.tie(0);int t;
cin >> t;while(t--){int n;
cin >> n;
vector<int>s(n);for(int i=0;i<n;i++) s[i]= i;
vector<int>a(n);for(int i=0;i<n;i++) cin >> a[i];
function<int(int)> FIND =[&](int x){return x == s[x]? x : s[x]=FIND(s[x]);};
vector<st> vs;
function<int()> kruskal =[&](){int num =0;int ans =0;for(int i=0;i<vs.size();i++){int x =FIND(vs[i].x);int y =FIND(vs[i].y);if(x == y)continue;
s[x]= y;
ans += vs[i].dis;if(num == n -1)break;}return ans;};for(int i=0;i<n;i++){for(int j=0;j<n;j++){int x;
cin >> x;if(i <= j)continue;
vs.push_back(st{i, j, x + a[i]+ a[j]});}}sort(vs.begin(), vs.end(),[&](st x, st y){return x.dis < y.dis;});
cout <<kruskal()<<'\n';}return0;}
6. poj 1789 Truck History
题意仔细理解一下,将每个字符串看作一个点,实际上是求这个图的最小生成树的权值和
#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<vector>#include<map>#include<iomanip>usingnamespace std;constint N =2e3+10;structst{int u, v, w;booloperator<(const st &B)const{return w < B.w;}}s[N * N];
string Data[N];int tot =0;int a =0;int b =0;int st[N];intFIND(int x){return x == st[x]? x : st[x]=FIND(st[x]);}voidKruskal(int n,int m){int num =0;for(int i=0;i<m;i++){int u =FIND(s[i].u);int v =FIND(s[i].v);int w = s[i].w;if(u == v)continue;
st[u]= v;
a += w;
num +=1;if(num == n -1)break;}}intmain(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int n;while(cin >> n && n){for(int i=0;i<n;i++){
cin >> Data[i];
st[i]= i;}
tot = a = b =0;for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){int sz =(int)Data[i].size();int w =0;for(int k=0;k<sz;k++){if(Data[i][k]!= Data[j][k]) w +=1;}
s[tot].u = i;
s[tot].v = j;
s[tot].w = w;
b += w;
tot +=1;}}sort(s, s + tot);Kruskal(n, tot);
cout <<"The highest possible quality is "<<1<<'/'<< a <<".\n";}return0;}
7. poj 2349 Arctic Network
之前做过了,应该也是个水题
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<iomanip>usingnamespace std;constint N =600;typedefdouble DB;const DB eps =1e-8;intcmp(double x){if(fabs(x)< eps)return0;return x <0?-1:1;}structst{int x, y;double z;booloperator<(const st &B)const{returncmp(z - B.z)<0;}}Data[N * N];int ss[N];intFIND(int x){return ss[x]== x ? x :ss[x]=FIND(ss[x]);}
vector<double> vec;voidKruskal(int n,int m){int num =0;for(int i=0;i<m;i++){int u = Data[i].x;int v = Data[i].y;double w = Data[i].z;
u =FIND(u);
v =FIND(v);if(u == v)continue;
ss[u]= v;
num +=1;
vec.push_back(w);if(num == n -1)break;}}
pair<double,double> vs[N];intmain(){int tt;
cin >> tt;while(tt--){int s, p;
cin >> s >> p;for(int i=1;i<=p;i++) ss[i]= i;int m =0;for(int i=1;i<=p;i++){
cin >> vs[i].first >> vs[i].second;}for(int i=1;i<=p;i++){for(int j=i+1;j<=p;j++){
Data[m].x = i;
Data[m].y = j;
Data[m].z =hypot(vs[i].first - vs[j].first, vs[i].second - vs[j].second);
m +=1;}}sort(Data, Data + m);
vec.clear();Kruskal(p, m);reverse(vec.begin(), vec.end());
cout << fixed <<setprecision(2)<<*(vec.begin()+ s -1)<<'\n';}return0;}
8. poj 1751 Highways
给你图中几条路径,补充完整最小生成树,已经构成路径的点放到一个集合里面即可,然后正常求
#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<vector>#include<map>#include<iomanip>usingnamespace std;typedeflonglong ll;constint N =760;int x[N], y[N];structst{int u, v;
ll w;booloperator<(const st &B)const{return w < B.w;}}s[N * N];int st[N];intFIND(int x){return x == st[x]? x : st[x]=FIND(st[x]);}intmain(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int n;
cin >> n;int tot =0;for(int i=0;i<n;i++){
cin >> x[i]>> y[i];
st[i]= i;}for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){
s[tot].u = i;
s[tot].v = j;
s[tot].w =1ll*(x[j]- x[i])*(x[j]- x[i])+1ll*(y[j]- y[i])*(y[j]- y[i]);
tot +=1;}}sort(s, s + tot);int m;
cin >> m;for(int i=0;i<m;i++){int u, v;
cin >> u >> v;
u -=1;
v -=1;
u =FIND(u);
v =FIND(v);if(u != v) st[u]= v;}
vector<pair<int,int>> vs;for(int i=0;i<tot;i++){int u =FIND(s[i].u);int v =FIND(s[i].v);int w = s[i].w;if(u == v)continue;
st[u]= v;
vs.push_back(make_pair(s[i].u +1, s[i].v +1));}for(int i=0;i<(int)vs.size();i++){
cout << vs[i].first <<' '<< vs[i].second <<'\n';}return0;}
9. poj 1258 Agri-Net
啊这,注意多测
#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<vector>#include<map>#include<iomanip>usingnamespace std;typedeflonglong ll;constint N =200;structst{int u, v;int w;booloperator<(const st &B)const{return w < B.w;}}s[N * N];int st[N];intFIND(int x){return x == st[x]? x : st[x]=FIND(st[x]);}intmain(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int n;while(cin >> n){int tot =0;for(int i=0;i<n;i++){
st[i]= i;for(int j=0;j<n;j++){int x;
cin >> x;if(i >= j)continue;
s[tot].u = i;
s[tot].v = j;
s[tot].w = x;
tot +=1;}}sort(s, s + tot);int ans =0;for(int i=0;i<tot;i++){int u =FIND(s[i].u);int v =FIND(s[i].v);int w = s[i].w;if(u == v)continue;
st[u]= v;
ans += w;}
cout << ans <<'\n';}return0;}
10. poj 3026 Borg Maze
这个题是个好题,说你在位置
S
S
S,现在要去每一个
A
A
A点,然后你走的过程中可以分裂,换句话说就是你不用走回头路,然后问你最少需要多长时间完成这个任务
真好久都没有遇到过这样的读入了,我不理解为什么
g
e
t
c
h
a
r
(
)
getchar()
getchar()读回车不对,涨姿势了,可以用sacnf(“%d%d\n”)读这个回车,然后这样读就能过,但是我用scanf("%d%d);getchar();就不行,也许是他输入没那么规范?
#include<iostream>#include<algorithm>#include<vector>#include<set>#include<map>usingnamespace std;constint N =200;int st[N], s_u[N], s_v[N];intFIND(int x){return x == st[x]? x : st[x]=FIND(st[x]);}structst{int u, v, w;booloperator<(const st &B)const{return w < B.w;}}s[N * N];intmain(){int t;
cin >> t;while(t--){int n, m;
cin >> n >> m;for(int i=1;i<=n;i++) st[i]= i;for(int i=0;i<m;i++){
cin >> s[i].u >> s[i].v >> s[i].w;}sort(s, s + m);int ans =0;bool ok =true;int now =0;for(int i=0;i<m;i++){int u =FIND(s[i].u);int v =FIND(s[i].v);int w = s[i].w;if(u == v)continue;
s_u[now]= s[i].u;
s_v[now]= s[i].v;
now +=1;
st[u]= v;
ans += w;}for(int i=0;i<now;i++){for(int j=1;j<=n;j++) st[j]= j;int res =0;int k =0;for(int j=0;j<m;j++){int u =FIND(s[j].u);int v =FIND(s[j].v);int w = s[j].w;if(u == v ||(s_u[i]== s[j].u && s_v[i]== s[j].v))continue;
res += w;
st[u]= v;
k +=1;}if(res == ans && k == n -1) ok =false;}if(ok) cout << ans <<'\n';else{
cout <<"Not Unique!"<<'\n';}}return0;}
如果按照常规想法,就是求这棵树的次小生成树,如果发现它也是最小生成树,那么就说明MST不唯一,基本想法就是把除了MST以外的最短边加入到MST中,这样一定出现了一个环,比如说我们加入的是
u
−
>
v
u->v
u−>v这条边,设权值为
w
w
w,如果发现
u
−
>
l
c
a
u->lca
u−>lca或者
v
−
>
l
c
a
v->lca
v−>lca这二者之间存在一条边边权等于
w
w
w,那么说明次小生成树不唯一
12. hdu 1233 还是畅通工程
裸题
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;structst{int u, v, w;booloperator<(const st &B)const{return w < B.w;}};intmain(){int n;while(~scanf("%d",&n)&& n !=0){int m = n *(n -1)/2;
vector<int>s(n +1);iota(s.begin(), s.end(),0);
function<int(int)> FIND =[&](int x){return x == s[x]? x : s[x]=FIND(s[x]);};
vector<st>edge(m);for(int i=0;i<m;i++){scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);}sort(edge.begin(), edge.end());int ans =0;for(int i=0;i<m;i++){int u =FIND(edge[i].u);int v =FIND(edge[i].v);if(u == v)continue;
s[u]= v;
ans += edge[i].w;}printf("%d\n", ans);}return0;}
13. hdu 1301 Jungle Roads
裸题,用string,省事
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;structst{int u, v, w;st(){}st(int u,int v,int w):u(u),v(v),w(w){}booloperator<(const st &B)const{return w < B.w;}};intmain(){int n;while(cin >> n && n){getchar();
vector<int>s(30);iota(s.begin(), s.end(),0);
function<int(int)> FIND =[&](int x){return x == s[x]? x : s[x]=FIND(s[x]);};
vector<st> edge;for(int i=0;i<n-1;i++){
string u;int m;
cin >> u >> m;for(int j=0;j<m;j++){
string v;int w;
cin >> v >> w;
edge.push_back(st(u[0]-'A', v[0]-'A', w));}}sort(edge.begin(), edge.end());int ans =0;for(int i=0;i<(int)edge.size();i++){int u =FIND(edge[i].u);int v =FIND(edge[i].v);if(u == v)continue;
s[u]= v;
ans += edge[i].w;}
cout << ans <<'\n';}return0;}
14. hdu 1875 畅通工程再续
这题没啥说的吧
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;structst{int u, v, w;st(){}st(int u,int v,int w):u(u),v(v),w(w){}booloperator<(const st &B)const{return w < B.w;}};intmain(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int t;
cin >> t;while(t--){int c;
cin >> c;
vector<pair<int,int>>vs(c);for(int i=0;i<c;i++){
cin >> vs[i].first >> vs[i].second;}
vector<st> v;
vector<int>s(c * c);iota(s.begin(), s.end(),0);
function<int(int)> FIND =[&](int x){return x == s[x]? x : s[x]=FIND(s[x]);};for(int i=0;i<c;i++){for(int j=i+1;j<c;j++){
v.push_back(st(i, j,(vs[i].first - vs[j].first)*(vs[i].first - vs[j].first)+(vs[i].second - vs[j].second)*(vs[i].second - vs[j].second)));}}sort(v.begin(), v.end());int num =0;double ans =0.0;for(int i=0;i<(int)v.size();i++){int u =FIND(v[i].u);int vv =FIND(v[i].v);if(u == vv || v[i].w <100)continue;if(v[i].w >1000*1000)break;
num +=1;
s[u]= vv;
ans +=sqrt(v[i].w)*100;}if(num != c -1) cout <<"oh!\n";else{
cout << fixed <<setprecision(1)<< ans <<'\n';}}return0;}