题意:一个不愿意做在bus等时间的人想去旅游,给出n个城市,m条道路和q个询问
题意思路参考:传送门
PS:暴力求n次最小生成树肯定超时、因为边的个数达到了10的5次方
1 #include<cmath> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 int n,m,q; 7 const int qq=20005; 8 int pre[qq]; 9 int sum[qq]; 10 int tar[qq]; 11 struct Edge 12 { 13 int u,v,w; 14 bool operator < (Edge a)const 15 { 16 return w<a.w; 17 } 18 }edge[qq*5]; 19 struct Query 20 { 21 int money; 22 int order; 23 bool operator < (Query b)const 24 { 25 return money<b.money; //总是忘记带return 26 } 27 }query[qq]; 28 int find(int x) 29 { 30 if(x==pre[x]) return x; 31 return pre[x]=find(pre[x]); 32 } 33 void slove() 34 { 35 for(int i=1;i<=n;++i){ 36 pre[i]=i; 37 sum[i]=1; //初始化每一个连通块 38 } 39 int ans=0; 40 int j=0; 41 for(int i=0;i<q;++i){ 42 for(;j<m && edge[j].w<=query[i].money;++j){ 43 int u,v; 44 u=edge[j].u;v=edge[j].v; 45 int x=find(u);int y=find(v); 46 if(x==y) continue; 47 ans+=sum[x]*sum[y]; //当连通块x和连通块y要形成一个新的连通块时,会增加多少两两组合的城市? 48 pre[y]=x; //这里的城市对是一个组合、不是有序对 49 //也就是说连通块x的每一个元素都可以和连通块y中的任意一个元素组成新的城市对 50 //所以这里是连通块x的元素个数去乘连通块y的元素个数、 51 sum[x]=sum[x]+sum[y]; //两个连通块连接成一个连通块、更新连通块的元素个数 52 } 53 tar[query[i].order]=ans*2; //因为是有序对、所以要乘2 、 54 } //对应顺序来填值、 55 for(int i=0;i<q;++i) 56 printf("%d ",tar[i]); 57 } 58 int main() 59 { 60 int t;scanf("%d",&t); 61 while(t--){ 62 scanf("%d%d%d",&n,&m,&q); 63 for(int i=0;i<m;++i) 64 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 65 for(int i=0;i<q;++i){ 66 scanf("%d",&query[i].money); 67 query[i].order=i; //记录标号、以便用数组来填值 68 } 69 sort(edge,edge+m); 70 sort(query,query+q); 71 slove(); 72 } 73 return 0; 74 }