HDU OJ 5441 Travel 2015online E
题目:click here
题意:
有个很暴躁的人,想坐车旅行n个城市。连接城市共有m条路(双向)。他坐在车上很不爽,每次最多忍耐x分钟。但是每站下车他又可以休息(重新计时)。总共有q次询问。问途中有多少条路他可以不爆发。a到b 和 b到a 算不同的路。 a 和 b 必须不相同。
分析:
并查集
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 5 using namespace std; 6 const int M = 2e4+5; 7 8 struct Edge { // 保存结点信息 9 int from, to, cost; 10 bool operator < ( const Edge x ) const { return cost < x.cost; } 11 } es[M*5]; 12 13 struct Query { // 保存问题信息 14 int val, id; 15 bool operator < ( const Query x ) const { return val < x.val; }; 16 } que[5005]; 17 18 int n, m, q; 19 int pre[M]; // 并查集 20 int ans[M]; // 答案 21 int sum[M]; // 记录并查集树高度 22 23 int find( int x ) { 24 return pre[x] == x ? x : pre[x] = find( pre[x] ); 25 } 26 void merge( int x, int y ) { 27 x = find( x ); y = find( y ); 28 if( sum[x] > sum[y] ) { sum[x] += sum[y]; pre[y] = x; } 29 else { sum[y] += sum[x]; pre[x] = y; } 30 } 31 void solve() { 32 scanf("%d%d%d", &n, &m, &q ); 33 for( int i=0; i<m; i++ ) 34 scanf("%d%d%d", &es[i].from, &es[i].to, &es[i].cost ); 35 sort( es, es+m ); 36 for( int i=0; i<q; i++ ) { 37 scanf("%d", &que[i].val ); 38 que[i].id = i; 39 } 40 sort( que, que+q ); 41 for( int i=0; i<=n; i++ ) { pre[i] = i; sum[i] = 1; } 42 int j = 0; 43 int res = 0; 44 for( int i=0; i<q; i++ ) { 45 for( ; j<m && que[i].val>=es[j].cost; j++ ) { 46 int x = find( es[j].from ); 47 int y = find( es[j].to ); 48 if( x == y ) continue; 49 res += sum[x] * sum[y]; 50 merge( es[j].from, es[j].to ); 51 } 52 ans[que[i].id] = res; 53 } 54 for( int i=0; i<q; i++ ) 55 printf("%d\n", ans[i]<<1 ); 56 } 57 58 int main() { 59 int t; scanf("%d", &t ); 60 while( t-- ) { 61 solve(); 62 } 63 64 return 0; 65 }