hdu 5441 Travel(Kruskal+离线)
生活随笔
收集整理的這篇文章主要介紹了
hdu 5441 Travel(Kruskal+离线)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5441
題意:
給定N個頂點,M條邊的一個無向圖,Q個詢問。對于每個詢問x,從a,b的路徑上各邊的最大權值小于x,可以記為有序對<a,b>, 求這個圖里面有多少個這樣的有序對。
解題思路:kruskal思想+離線。首先把邊從小到大排序,對于某個限制limit,如果邊小于等于limit,則表示這條邊是符合要求的,用并查集加入到連通塊去,并且假設還要記得更新點對的個數,比如加入的這條邊的兩個頂點(u,v),它們所屬的連通塊的個數為sum1和sum2,則兩個連通塊合并后點對增加了sum1*sum2個。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;struct Edge {int u,v,d; }edge[100005]; struct Query {int d,idx; }que[5005]; int n,m,q,fa[20005],sum[20005]; int ans[5005],tot;bool cmp(Edge a,Edge b) {return a.d < b.d; }bool cmp1(Query a,Query b) {return a.d < b.d; }int find(int x) {if(fa[x] == x) return x;return fa[x] = find(fa[x]); }int main() {int t;scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&q);for(int i = 1; i <= n; i++) {fa[i] = i;sum[i] = 1;}for(int i = 1; i <= m; i++)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].d);for(int i = 1; i <= q; i++){scanf("%d",&que[i].d);que[i].idx = i;}sort(edge+1,edge+1+m,cmp);sort(que+1,que+1+q,cmp1);int cnt = 1;tot = 0;for(int i = 1; i <= m; i++){int u = edge[i].u;int v = edge[i].v;int fu = find(u);int fv = find(v);while(que[cnt].d < edge[i].d && cnt <= q){ans[que[cnt].idx] = tot;cnt++;}ans[que[cnt].idx] = tot;if(fu != fv){fa[fv] = fu;tot += sum[fu] * sum[fv];sum[fu] += sum[fv];ans[que[cnt].idx] = tot;}}for(int i = cnt + 1; i <= q; i++)ans[que[i].idx] = tot;for(int i = 1; i <= q; i++)printf("%d\n",2*ans[i]);}return 0; }
總結
以上是生活随笔為你收集整理的hdu 5441 Travel(Kruskal+离线)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Activiti 学习记录1 inclu
- 下一篇: Groovy的基础语法