hdu3938(最小生成树,推荐)
题意描述:简单的讲就是,给你一张无向图,求有多少条路径使得路径上的花费小于L,这里路径上的花费是这样规定的,a、b两点之间的多条路径中的最长的边最小值!
思路:这题目有多个询问,肯定要用离线输出。思路的话,我们只需要从小到达枚举边的长度,如果两个并查集没有连通,那么联通之后的路径条数就应该是(num[a]*num[b])........
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int father[10005],num[10005]; struct node { int v1,v2; int dis; }s[50005]; struct node1 { int ans; int sum; int id; }t[10005]; int cmp(const node a,const node b) { if(a.dis<b.dis) return 1; else return 0; } int cmp1(const node1 a,const node1 b) { if(a.sum<b.sum) return 1; else return 0; } int cmp2(const node1 a,const node1 b) { if(a.id<b.id) return 1; else return 0; } int find(int x) { int root,i=x; while(x!=father[x]) x=father[x]; root=x; x=i; while(x!=father[x]) { i=father[x]; father[x]=root; num[root]+=num[x]; num[x]=0; x=i; } return root; } int liantong(int x,int y) { father[x]=y; int k=num[y]*num[x]; num[y]+=num[x]; num[x]=0; return k; } int main() { int n,m,q; while(scanf("%d%d%d",&n,&m,&q)>0) { for(int i=0;i<=n;i++) { father[i]=i; num[i]=1; } int maxn=0; for(int i=0;i<m;i++) { scanf("%d%d%d",&s[i].v1,&s[i].v2,&s[i].dis); maxn=s[i].dis; } sort(s,s+m,cmp); //int q; //scanf("%d",&q); //q= for(int i=0;i<q;i++) { scanf("%d",&t[i].sum); t[i].id=i; } sort(t,t+q,cmp1); int j=0; for(int i=0;i<q;i++) { if(i==0) t[i].ans=0; else t[i].ans=t[i-1].ans; while(j<m&&t[i].sum>=s[j].dis) { int tmp=s[j].v1; int tmp1=s[j].v2; tmp=find(tmp); tmp1=find(tmp1); if(tmp!=tmp1) { t[i].ans+=liantong(tmp,tmp1); } j++; } } sort(t,t+q,cmp2); for(int i=0;i<q;i++) printf("%d\n",t[i].ans); } return 0; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。