HDU 3938 离线+并查集(Java版)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3938
题目大意为:求有多少个点对满足要求L>=min{T},这里的T指的是两个点之间联通的一条路径上的最长的边的长度,两个点之间有很多路径。
emm,最开始题目都没读懂。
然后参考了下面这位博主的做法:https://blog.csdn.net/sdj222555/article/details/7439187
先输入所有的边和L,对所有的L进行排序,对所有的边进行排序,都为从小到大,然后对每个L,将比其小的边权的边都并在一起,计算种类数即可。
AC代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;

//离线加并查集
//题目大意为:求有多少个点对满足要求L>=min{T},这里的T指的是两个点之间联通的一条路径上的最长的边的长度,两个点之间有很多路径。
//也就是求两点之间所有路径上最长边的最小值满足<=L
public class Main {
	static int maxn=10005;
	static int maxm=50005;
	static int num[]=new int[maxn];//存储满足要求的点对数
	static int fa[]=new int[maxn];
	static class edge implements Comparable<edge>{
		int u,v,cost;
		public edge(int u, int v, int cost) {
			super();
			this.u = u;
			this.v = v;
			this.cost = cost;
		}
		@Override
		public int compareTo(edge ed) {
			return (this.cost-ed.cost);
		}			
	}
	static class P implements Comparable<P>{
		int id,l;

		@Override
		public int compareTo(P p) {
			return this.l-p.l;
		}

		public P(int id, int l) {
			super();
			this.id = id;
			this.l = l;
		}
		
	}
	static P p[]=new P[maxn];
	static edge e[]=new edge[maxm];
	static int find(int x){
		return x==fa[x]?x:(fa[x]=find(fa[x]));
	}
	static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
	public static void main(String[] args) throws IOException {
		while(st.nextToken()!=StreamTokenizer.TT_EOF){
			int n,m,q;
			n=(int)st.nval;
			m=nextInt();
			q=nextInt();
			int a,b,c;
			for(int i=0;i<=n;i++){
				fa[i]=i;
				num[i]=1;
			}
			for(int i=0;i<m;i++){
				a=nextInt();
				b=nextInt();
				c=nextInt();
				e[i]=new edge(a,b,c);
			}
			Arrays.sort(e,0,m);
			for(int i=0;i<q;i++){
				int l=nextInt();
				p[i]=new P(i,l);
			}
			Arrays.sort(p,0,q);
			long ans=0;
			int pos=0;
			long goal[]=new long[q];
			for(int i=0;i<q;i++){
				while(pos<m&&e[pos].cost<=p[i].l){
					ans+=merge(e[pos].u,e[pos].v);
					pos++;
				}
				goal[p[i].id]=ans;
			}
			for(int i=0;i<q;i++){
				out.println(goal[i]);
			}
			out.flush();
		}
	}
	static long merge(int u, int v) {
		int x=find(u);
		int y=find(v);
		if(x==y)
			return 0;
		int t=num[x]*num[y];
		num[x]+=num[y];
		num[y]=0;
		fa[y]=x;		
		return t;
	}
	static int nextInt(){
		try {
			st.nextToken();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return (int)st.nval;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值