HDU 5723 Abandoned country
阿新 • • 發佈:2018-12-13
#include "bits/stdc++.h" using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define fori(i,l,u) for(int i = l;i < u;i++) #define forj(j,l,u) for(int j = l;j < u;j++) #define F first #define S second #define pb push_back #define mk make_pair typedef long long ll; typedef pair<int, int> pi; typedef pair<string, int> ps; typedef vector<int> vi; typedef vector<string> vs; typedef vector<pi> vpi; const int maxn = 1e5 + 6; int t; ll n,m; //n是村莊,m是道路 ll ans; //最小生成樹的權值 ll node[maxn],rk[maxn]; ll sum[maxn],dp[maxn]; typedef struct { ll u; ll v; ll w; }road; road R[maxn * 10]; typedef struct { ll v; ll w; }N; vector<N> tree[maxn]; void init(){ //初始化 ans = 0; mem(sum,0); mem(dp,0); fori(i, 1, n+1){ node[i] = i; rk[i] = 0; tree[i].clear(); } } ll find(ll x){ if (x == node[x]) { return x; } return node[x] = find(node[x]); } void merge(ll x,ll y){ x = find(x); y = find(y); if (rk[x] < rk[y]) { node[x] = y; } else{ node[y] = x; if (rk[x] == rk[y]) { rk[x] ++; } } } bool compare(const road& x,const road &y){ return x.w < y.w; } void Kruskal(ll m){ int num = 0; for(int i = 0;i < m && num != n-1 ;i++){ if (find(R[i].u) != find(R[i].v)) { num ++; ans += R[i].w; merge(R[i].u,R[i].v); // 新增最小生成樹 N t1,t2; t1.v = R[i].u; t1.w = R[i].w; t2.v = R[i].v; t2.w = R[i].w; tree[R[i].v].pb(t1); tree[R[i].u].pb(t2); } } } void dfs(ll cur,ll ft){ sum[cur] = 1; fori(i, 0, tree[cur].size()){ ll son = tree[cur][i].v; ll len = tree[cur][i].w; if (ft == son) { //至關重要 continue; } dfs(son, cur); sum[cur] += sum[son]; dp[cur] += dp[son] + (n-sum[son])*sum[son]*len; } } int main() { // freopen("1.txt", "r", stdin); scanf("%d",&t); while (t--) { scanf("%lld%lld",&n,&m); init(); fori(i, 0, m){ //道路的標號從0開始 scanf("%lld%lld%lld",&R[i].u,&R[i].v,&R[i].w); } sort(R, R+m,compare); Kruskal(m); ll cur = 0; fori(i, 1, n+1){ if (node[i] == i) { cur = i; break; } } dfs(cur, -1); double num = n*(n-1)/2; cout<<ans<<" "; printf("%.2lf\n",(double)dp[cur]/num); } return 0; }
此程式碼和上述兩題的結構一樣,基本上是抄板子的。
- 遇到的問題 : 說的輕鬆,遇到的問題真是。。心酸 1)注意n和m的範圍,一個是10w,一個是100w,設定maxn = 1e5 + 6,然後邊的結構體陣列的範圍是 10 * maxn。 2)int會wa。。雖然不知道為什麼,有一道最小生成樹還是樹形dp的題也是這樣,不過都改成ll肯定沒錯。。 3)cin會wa,這兩種型別的題,最小生成樹,樹形dp,一般都用scanf,有的題會有hint : scanf recommend 4)dfs和Kruskal注意邊界問題。