J - 天空之城
由该题走过的路不消耗时间,那么我们只需要把最短路依次加入到答案中即可。
用并查集作为查询以便在 O(1) 时间内知道这片区域是否联通
#include<iostream> #include<algorithm> #include<unordered_map> using namespace std; #define ll long long int n ,m; const int N = 5e3 , M = 2e5 ; struct G{ int x, y; ll w; bool operator < (const G &X) const { return w < X.w; } }g[M]; int fa[N]; int find(int x){ if(x == fa[x]) return x; return fa[x] = find(fa[x]); } int main(){ while(cin >> n >> m){ for(int i = 1 ; i <= n ; i ++) fa[i] = i; unordered_map<string,int> ID; string a , b; cin >> a; int id = 0; ll x; for(int i = 1 ; i <= m ; i ++){ cin >> a >> b; scanf("%lld",&x); if(ID[a] == 0) ID[a] = ++ id; if(ID[b] == 0) ID[b] = ++ id; g[i] = (G){ID[a] , ID[b] ,x } ; } sort(g+1,g+1+m); ll ans = 0; for(int i = 1 ; i <= m ; i ++){ int fx = find(g[i].x) , fy = find(g[i].y); if(fx == fy) continue; fa[fx] = fy; ans += g[i].w; } x = find(fa[1]) ; bool f = true; for(int i = 1 ; i <= n ; i ++){ if(find(fa[i]) != x){ puts("No!"); f = false; break; } } if(f) printf("%lld\n",ans); } return 0; }