HDU - 5441 Travel 离线处理+并查集
生活随笔
收集整理的這篇文章主要介紹了
HDU - 5441 Travel 离线处理+并查集
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意
給我們一個圖 給出這個圖的n個點 和m個邊和權值 然后再分別給我們q個查詢 每個查詢給一個x 讓我們在這個圖中找出多少個不同的有序?qū)?使得從x到y(tǒng)的最大權值不超過x n≤20000,m≤100000,q≤5000.分析
20000個點 1000ms 暴力肯定不行 看似這道題像是個圖論的題 嘿嘿嘿 其實。。。 我們看 如何找出符合題目條件所需要的對數(shù)呢 我們?nèi)绻麑θ我庖粋€查詢 我們對一條新的邊考慮如果這條新的邊其權值滿足當前查詢 那么就把他算進來 那么我們要繼續(xù)找邊 我們肯定不能找大的邊 因為大的邊肯定滿足不了當前查詢 所以我們還是要從小邊找起來 所以我們要對邊進行排序 然后對一個查詢 我們也最好從小的查詢搞起來 因為小查詢的結果一定滿足大查詢的結果 如果不要重復計算 我們就需要從小的查詢開始 那么這里就考慮離線處理 一個小的查詢的結果是可以轉(zhuǎn)移到大的查詢的結果 這樣可以更迅速的把q個查詢算出來 確定了這兩點 我們再看如何把一個查詢的值求出來 我們不是要枚舉邊么 那么如何才能做到有效統(tǒng)計并轉(zhuǎn)移小查詢的結果給大查詢呢? 假設我們已經(jīng)找到了好幾個符合條件的邊 有些邊是組成一個聯(lián)通塊 有些邊組成不同聯(lián)通塊 對于符合條件的聯(lián)通塊 我們一定要對這個塊進行計數(shù) 就是從這個塊中的數(shù)量中選出兩個元素來的所有可能 如果來了一條新邊 這條邊 有兩種可能1 這條邊屬于某個聯(lián)通塊2 此邊形成新的聯(lián)通塊 情況1 : 我們就需要把這條邊的新點加進去 也就是把當前新點的數(shù)量n1 * 原來聯(lián)通塊中的舊點n2 *2 (雙向) 情況2 : 那么我們就需要把這個新塊 同情況一的算法算一下 累計結果 下一次查詢可以重復利用 那么這里我們就可以考慮并查集了 對于一個并查集元素 我們記錄這個點的father 和 本塊內(nèi)的數(shù)量 初始化f = 自己 數(shù)量 = 1 沒得到一個新邊我們就查詢邊的兩頭的點的父親是否為同一個 不同就合并 并累計數(shù)量 問題就解決了 這道題還是考慮一個如何順序化考慮解 如何把符合條件的聯(lián)通塊計數(shù)問題轉(zhuǎn)化為邊的問題 如何把小查詢結果轉(zhuǎn)移到大的查詢的問題CODE
#include<bits/stdc++.h> using namespace std; struct node{int num,f; }n[20010]; int N,M,Q,ans[5010]; struct edge{int s,e,w; }e[100010]; bool cmp(edge a,edge b){return a.w<b.w;//對于edge把權值小的放前面 } struct ques{int id,que;bool operator<(const ques &a){return que<a.que;//q值小的排前面 } }Qe[5010]; int find(int x){int j=x;while(j!=n[j].f){j = n[j].f;}int i,k=x;while(k!=n[k].f){i = n[k].f;n[k].f=j;k = i;}return j; } int main() {int t;scanf("%d",&t);while(t--){scanf("%d%d%d",&N,&M,&Q);memset(ans+1,0,sizeof(int)*Q);for(int i=1;i<=N;i++){n[i].num=1;n[i].f=i; }for(int i=1;i<=M;i++){scanf("%d%d%d",&e[i].s,&e[i].e,&e[i].w);}sort(e+1,e+1+M,cmp);for(int i=1;i<=Q;i++)scanf("%d",&Qe[i].que),Qe[i].id = i;sort(Qe+1,Qe+1+Q);int ce=1;//邊記錄位置 int cnt=0;for(int i=1; i<=Q ;i++){//枚舉q for(; ce<=M&&e[ce].w<=Qe[i].que ;ce++){// ce<=M leakint f1 = find(e[ce].s);int f2 = find(e[ce].e);if(f1!=f2){n[f2].f=f1;cnt+=n[f1].num*n[f2].num*2; n[f1].num+=n[f2].num;}} ans[Qe[i].id]+=cnt; } for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);}return 0; }總結
以上是生活随笔為你收集整理的HDU - 5441 Travel 离线处理+并查集的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS-键盘事件之方向键移动元素
- 下一篇: Java word转pdf方法