标签:eth reac split positive 结束 cer font ane hit
唉,被班级合唱和复变考试搞得心力交瘁。新算法学不进去,更新下吧
9 A 2 B 12 I 25 B 3 C 10 H 40 I 8 C 2 D 18 G 55 D 1 E 44 E 2 F 60 G 38 F 0 G 1 H 35 H 1 I 35 3 A 2 B 10 C 40 B 1 C 20 0Sample Output
216 30
思路:把字母转换成节点编号套下板子就可以了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 50500;
///把所有边排序,记第i小的边为:e[i](1 <= i < m)
///初始化MST为空
///初始化连通分量,让每个点自成一个独立的连通分量
///for(int i = 0; i < m; i++) {
/// if(e[i].u 和 e[i].v 不在同一个连通分量) {
/// 把边e[i]加入MST
/// 合并e[i].u 和 e[i].v 所在的连通分量
/// }
///}
int fa[50500],n,m,ans,eu,ev,cnt,t; struct node{ int u, v, w; }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void kruskal() { sort(e, e+m, cmp); for(int i = 0; i < m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; /*if(++cnt == n-1) { break; }*/ } } int main() { while(scanf("%d",&n)) { if(!n) break; for(int i = 1; i <= 28; i++) { fa[i] = i; } int t = n-1; m = 0; ans = 0; while(t--) { char ch; int num; cin >> ch >> num; while(num--) { char vge; int cost; cin >> vge >> cost; e[m].u = ch-64; e[m].v = vge-64; e[m].w = cost; m++; } } /*for(int i = 0; i < m; i++) { printf("e[%d].u:%d e[%d].v:%d e[%d].w:%d\n",i,e[i].u,i,e[i].v,i,e[i].w); }*/ kruskal(); printf("%d\n",ans); } return 0; }
1 0 2 3 1 2 37 2 1 17 1 2 68 3 7 1 2 19 2 3 11 3 1 7 1 3 5 2 3 89 3 1 91 1 2 32 5 7 1 2 5 2 3 7 2 4 8 4 5 11 3 5 10 1 5 6 4 2 12 0Sample Output
0 17 16 26
思路:板子题
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt; struct node{ int u, v, w; }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } bool unite(int r1, int r2) { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int n, int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { //printf("!!! i:%d n:%d m:%d\n",i,n,m); if(unite(e[i].u,e[i].v)) { cnt++; ans += e[i].w; //printf("ans:%d\n",ans); } if(cnt == n-1) { break; } } } int main() { while(scanf("%d",&n) && n) { scanf("%d",&m); init(n); for(int i = 1; i <= m; i++) { scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w); } kruskal(n,m); printf("%d\n",ans); } return 0; }
3 10.000 10.000 50.000 10.000 40.000 10.000 50.000 10.000 40.000 40.000 50.000 10.000 2 30.000 30.000 30.000 20.000 40.000 40.000 40.000 20.000 5 5.729 15.143 3.996 25.837 6.013 14.372 4.818 10.671 80.115 63.292 84.477 15.120 64.095 80.924 70.029 14.881 39.472 85.116 71.369 5.553 0Sample Output
20.000 0.000 73.834
思路:把所有点先存起来,算出每个点之间的距离。
注意:POJ这个东西得double,G++和C++轮着交
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m; double ans; int eu,ev,cnt; struct node { int u,v; double w; }e[maxn]; struct Node { double x,y,z,r; }a[maxn]; bool cmp(node a, node b) { return a.w < b.w; } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } bool unite(int r1, int r2) { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; //if(++cnt == n-1) { //break; //} } } int main() { while(scanf("%d",&n) && n) { for(int i = 1; i <= n; i++) { scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z,&a[i].r); } //int u,v,w; int num = 1; for(int i = 1; i < n; i++) { for(int j = i+1; j <= n; j++) { e[num].u = i, e[num].v = j; double temp; temp = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)+(a[i].z-a[j].z)*(a[i].z-a[j].z))- a[i].r - a[j].r; temp = max(0.0,temp); e[num].w = temp; num++; } } num--; init(n); kruskal(num); printf("%.3lf\n",ans); } return 0; }
3 0 990 692 990 0 179 692 179 0 1 1 2Sample Output
179
思路:存点算间距,给出的已连通的直接让他们距离为0就可以了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt; struct node{ int u, v, w; }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; if(++cnt == n-1) { break; } } } int main() { while(scanf("%d",&n)!=EOF) { int num = 1; int temp; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { cin >> temp; if(i == j) continue; e[num].u = i, e[num].v = j; e[num].w = temp; num++; } } num--; int q; cin >> q; while(q--) { int x,y; cin >> x >> y; for(int i = 1; i <= num; i++) { if(e[i].u == x && e[i].v == y) { e[i].w = 0; } if(e[i].u == y && e[i].v == x) { e[i].w = 0; } } } init(n); kruskal(num); printf("%d\n",ans); } return 0; }
4 aaaaaaa baaaaaa abaaaaa aabaaaa 0Sample Output
The highest possible quality is 1/3.
思路:题意有点难以理解,模拟下给出的公式就知道什么意思了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 6e6+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt; struct node { int u, v, w; }e[maxn]; struct Node { char s[10]; }a[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; if(++cnt == n-1) { break; } } } int main() { while(scanf("%d",&n) && n) { for(int i = 1; i <= n; i++) { cin >> a[i].s; //printf("len:%d\n",a[i].s.length()); } int num = 1; for(int i = 1; i < n; i++) { for(int j = i+1; j <= n; j++) { e[num].u = i, e[num].v = j; int temp = 0; for(int k = 0; k < 7; k++) { if(a[i].s[k] != a[j].s[k]) temp++; } e[num].w = temp; num++; } } num--; init(n); kruskal(num); printf("The highest possible quality is 1/%d.\n",ans); } return 0; }
1 2 4 0 100 0 300 0 600 150 750Sample Output
212.13
思路:存点算距离
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt; struct node{ int u, v; double w; }e[maxn]; struct Node { double x,y; }a[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int n,int s,int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; //printf("cnt:%d n-s:%d\n",cnt+1,n-s); if(++cnt == n-s) { printf("%.2lf\n",e[i].w); break; } } } int main() { int t; scanf("%d",&t); while(t--) { int s,n; scanf("%d %d",&s,&n); for(int i = 1; i <= n; i++) { scanf("%lf %lf",&a[i].x,&a[i].y); } int num = 1; for(int i = 1; i <= n; i++) { for(int j = i+1; j <= n; j++) { e[num].u = i, e[num].v = j; e[num].w = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)); num++; } } /*for(int i = 1; i <= num; i++) { printf("e[%d]:%lf\n",i,e[i].w); }*/ num--; init(n); kruskal(n,s,num); } return 0; }
9 1 5 0 0 3 2 4 5 5 1 0 4 5 2 1 2 5 3 3 1 3 9 7 1 2Sample Output
1 6 3 7 4 9 5 7 8 3
思路:多组输入wa,存点计算各点之间的距离,然后kruskal
#include<cstdio> #include<iostream> #include<algorithm> #include<string> #include<cstring> using namespace std; const int maxn = 1055; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt; struct Node { int x, y; }a[maxn]; void init(int n) { cnt = 0; ans = 0; for (int i = 0; i <= n; i++) fa[i] = i; } struct node { int u, v, w; bool operator < (const node& A) const { return w < A.w; } }edge[maxn * maxn]; int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal() { sort(edge, edge + m); for (int i = 0; i < m; i++) { int u = edge[i].u, v = edge[i].v, w = edge[i].w; if (unite(u, v)) { printf("%d %d\n", u, v); cnt++; if (cnt == n -1 ) break; } } } int main() { scanf("%d", &n); { m = 0; for (int i = 1; i <= n; i++) { scanf("%d%d", &a[i].x, &a[i].y); for (int j = 1; j < i; j++) { edge[m].u = i; edge[m].v = j; edge[m++].w = (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y); } } int Q; scanf("%d", &Q); while (Q--) { int a, b; scanf("%d%d", &a, &b); if (unite(a, b)) cnt++; } kruskal(); } return 0; }
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0Sample Output
28
思路:存点计算各点间距,然后kruskal
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2e5+7; typedef long long LL; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m; LL ans; int eu,ev,cnt; struct node{ int u, v, w; }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int n, int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; if(++cnt == n-1) { break; } } } int main() { while(scanf("%d",&n)!=EOF) { int num = 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { int temp; scanf("%d",&temp); if(i != j) { e[num].w = temp; e[num].u = i, e[num].v = j; num++; } } } num--; init(n); kruskal(n,num); printf("%lld\n",ans); } return 0; }
2 6 5 ##### #A#A## # # A# #S ## ##### 7 7 ##### #AAA### # A# # S ### # # #AAA### #####Sample Output
8 11
思路:对每个S或A进行编号,bfs求各点之间互相到达的最短距离建图,然后kruskal
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt,xx,yy; char maze[60][60]; int a[60][60]; int dr[4] = {1, 0, -1, 0}; int dc[4] = {0, 1, 0, -1}; int num; bool vis[60][60]; struct node { int u, v, w; }e[maxn]; struct Node { int x, y; int step; }; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal() { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; if(++cnt == n-1) { //break; } } } void bfs(int x, int y, int ans) { memset(vis,0,sizeof(vis)); queue <Node> q; Node temp; temp.x = x, temp.y = y, temp.step = 0; vis[x][y] = 1; q.push(temp); while(!q.empty()) { temp = q.front(); q.pop(); for(int i = 0; i < 4; i++) { Node nxt; nxt.x = temp.x + dr[i]; nxt.y = temp.y + dc[i]; nxt.step = temp.step + 1; //printf("a[%d][%d]:%d vis[%d][%d]:%d\n",nxt.x,nxt.y,a[nxt.x][nxt.y],nxt.x,nxt.y,vis[nxt.x][nxt.y]); if(nxt.x >= 1 && nxt.y >= 1 && nxt.x <= xx && nxt.y <= yy && !vis[nxt.x][nxt.y] && a[nxt.x][nxt.y] != -1) { vis[nxt.x][nxt.y] = 1; q.push(nxt); //printf("a[%d][%d] : %d\n",nxt.x,nxt.y,a[nxt.x][nxt.y]); if(a[nxt.x][nxt.y] > 0) { e[m].u = ans, e[m].v = a[nxt.x][nxt.y]; e[m++].w = nxt.step; //printf("u:%d v:%d w:%d\n",e[m-1].u,e[m-1].v,e[m-1].w); //printf("num!:%d\n",m); } } } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d %d",&yy, &xx); getchar(); n = 1, m = 1; memset(a,0,sizeof(a)); for(int i = 1; i <= xx; i++) { char ch[60]; gets(ch); for(int j = 0; j < yy; j++) { if(ch[j] == ‘#‘) a[i][j+1] = -1; else if(ch[j] == ‘A‘ || ch[j] == ‘S‘) a[i][j+1] = n++; else if(ch[j] == ‘ ‘) a[i][j+1] = 0; //printf("a[%d][%d]:%d\n",i,j+1,a[i][j+1]); } } //printf("\n"); for(int i = 1; i <= xx; i++) { for(int j = 1; j <= yy; j++) { if(a[i][j] > 0) { bfs(i,j,a[i][j]); //printf("num:%d\n",m); } } } //printf("n:%d m:%d\n",n,m); n--; m--; init(n); kruskal(); printf("%d\n",ans); } return 0; }
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2Sample Output
3 Not Unique!
思路:对于唯一生成树问题,我们可以通过对重边的标记,在进行kruskal时跳过用过的重边,判断是否能够找到边权相同的最小生成树。也有另外一种通过求次小生成树来判断MST是否唯一的方法,后续会补上。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt,ok,flag; struct node{ int u, v, w; int used,del,rep;//使用过,删掉惹,重复边 }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; e[i].del = 0, e[i].rep = 0, e[i].used = 0; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } int kruskal(int m) { ans = 0; for(int i = 1; i <= m; i++) { //printf("!\n"); if(e[i].del) continue; //printf("?\n"); eu = fid(e[i].u); ev = fid(e[i].v); //printf("eu:%d ev:%d\n",eu,ev); if(eu == ev) { continue; } ans += e[i].w; //cout << "e[i].w:" << e[i].w << endl; if(!flag) e[i].used = 1; fa[ev] = eu; //printf("ok:%d e[i].w:%d e[i-1].w:%d\n",ok,e[i].w,e[i-1].w); if(++cnt == n-1) { break; } } //printf("ans:%d\n",ans); return ans; } int main() { int t; scanf("%d",&t); while(t--) { ok = 0; scanf("%d %d",&n,&m); for(int i = 1; i <=m; i++) { scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w); } init(n); for(int i = 1; i <= m; i++) { for(int j = 1; j <= m; j++) { if(j == i) continue; if(e[i].w == e[j].w) { e[i].rep = 1; //printf("e[%d]:%d\n",i,e[i].rep); } } } flag = 0; sort(e+1, e+m+1, cmp); int res = kruskal(m); flag = 1; for(int i = 1; i <= n; i++) { //printf("e[%d]:%d\n",i,e[i].rep); if(e[i].rep == 1 && e[i].used == 1) { //init(n); e[i].del = 1; int temp; for(int g = 1; g <= n ; g++) { fa[g] = g; } temp = kruskal(m); e[i].del = 0; //printf("temp:%d\n",temp); if(temp == res) { printf("Not Unique!\n"); ok = 1; break; } } } if(!ok) { printf("%d\n",res); } } return 0; }
3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0Sample Output
3 5 Huge input, scanf is recommended.Hint
Hint
思路:建图+kruskal
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,ans,eu,ev,cnt; struct node{ int u, v, w; }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0; cnt = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; if(++cnt == n-1) { break; } } } int main() { m = 1; while(scanf("%d",&n) && n) { int m = n * (n-1) / 2; for(int i = 1; i <= m; i++) { scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w); } init(n); kruskal(m); printf("%d\n",ans); } return 0; }
9 A 2 B 12 I 25 B 3 C 10 H 40 I 8 C 2 D 18 G 55 D 1 E 44 E 2 F 60 G 38 F 0 G 1 H 35 H 1 I 35 3 A 2 B 10 C 40 B 1 C 20 0Output
216 30Sample Input
9 A 2 B 12 I 25 B 3 C 10 H 40 I 8 C 2 D 18 G 55 D 1 E 44 E 2 F 60 G 38 F 0 G 1 H 35 H 1 I 35 3 A 2 B 10 C 40 B 1 C 20 0Sample Output
216 30
思路:别问,问就是bin巨的锅
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 50500; int fa[50500],n,m,ans,eu,ev,cnt,t; struct node{ int u, v, w; }e[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void kruskal() { sort(e, e+m, cmp); for(int i = 0; i < m; i++) { eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } ans += e[i].w; fa[ev] = eu; /*if(++cnt == n-1) { break; }*/ } } int main() { while(scanf("%d",&n)) { if(!n) break; for(int i = 1; i <= 28; i++) { fa[i] = i; } int t = n-1; m = 0; ans = 0; while(t--) { char ch; int num; cin >> ch >> num; while(num--) { char vge; int cost; cin >> vge >> cost; e[m].u = ch-64; e[m].v = vge-64; e[m].w = cost; m++; } } /*for(int i = 0; i < m; i++) { printf("e[%d].u:%d e[%d].v:%d e[%d].w:%d\n",i,e[i].u,i,e[i].v,i,e[i].w); }*/ kruskal(); printf("%d\n",ans); } return 0; }
2 2 10 10 20 20 3 1 1 2 2 1000 1000Sample Output
1414.2
思路:建图后kruskal,注意一些细节,比如double和对t比到1e(-6)级,另外一些题意上的坑点详见hdu里此题讨论区
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn = 2e5+7; ///把所有边排序,记第i小的边为:e[i](1 <= i < m) ///初始化MST为空 ///初始化连通分量,让每个点自成一个独立的连通分量 ///for(int i = 0; i < m; i++) { /// if(e[i].u 和 e[i].v 不在同一个连通分量) { /// 把边e[i]加入MST /// 合并e[i].u 和 e[i].v 所在的连通分量 /// } ///} int fa[5050],n,m,eu,ev,cnt,ok; double ans; struct node{ int u, v; double w; }e[maxn]; struct Node { int x,y; }a[maxn]; bool cmp(node a, node b) { return a.w < b.w; } int fid(int x) { return x == fa[x] ? x : fid(fa[x]); } void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; } ans = 0.0; cnt = 0; ok = 0; } bool unite(int r1, int r2)///冰茶鸡 { int fidroot1 = fid(r1), fidroot2 = fid(r2); if(fidroot1 != fidroot2) { fa[fidroot2] = fidroot1; return true; } return false; } void kruskal(int m) { sort(e+1, e+m+1, cmp); for(int i = 1; i <= m; i++) { //printf("e[%d]:%f\n",i,e[i].w); eu = fid(e[i].u); ev = fid(e[i].v); if(eu == ev) { continue; } if(e[i].w >= 10.000000 && e[i].w <= 1000.0000001) { ans += e[i].w; fa[ev] = eu; //printf("ans:%.1f cnt:%d\n",ans,cnt); if(++cnt == n-1) { ok = 1; break; } } } if(ok) { printf("%.1f\n",ans * 100); } else { printf("oh!\n"); } } double dist(Node a, Node b) { return sqrt((a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y)); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%d %d",&a[i].x,&a[i].y); } m = 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(i == j) { continue; } else { e[m].u = i, e[m].v = j; e[m++].w = dist(a[i],a[j]); } } } m--; init(n); kruskal(m); } return 0; }
标签:eth reac split positive 结束 cer font ane hit
原文地址:https://www.cnblogs.com/orangeko/p/11874425.html