计蒜客 回收元件 拓扑排序(Java版)

题目大意:将各个元件按照某个次序向y轴负半轴移动,直到所有元件全部移出工作区,我的想法是如果a元件的左端点横坐标在b元件两个端点的横坐标中间时,判断a元件左端点的纵坐标ya与a元件左端点横坐标在b元件上的纵坐标位置yb,如果ya大于yb,说明要先移动b元件,所以我们可以建图点b指向a,a点的入度增加,n^2遍历所有的元件之后可以得到一个图,然后进行拓扑排序输出即可。
ac代码:

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
	static class edge {
		int x1,y1,x2,y2;
		edge(int a,int b,int c,int d){
			x1=a;
			y1=b;
			x2=c;
			y2=d;
		}		
	}
	static class bian{//用来存边的邻接表
		int v,next;
		bian(int v,int next){
			this.v=v;
			this.next=next;
		}
	}
	static int p[]=new int[6005];
	static bian b[]=new bian[5000000];//刚开始开200万发现不够
	static int eid=0;
	static void insert(int u,int v){
		b[eid]=new bian(v,p[u]);
		p[u]=eid++;
	}
	static edge e[]=new edge[6005];
	static int rudu[]=new int[6005];//存储元件的入度
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		Arrays.fill(p, -1);
		for(int i=1;i<=n;i++){
			int a=sc.nextInt();
			int b=sc.nextInt();
			int c=sc.nextInt();
			int d=sc.nextInt();
			if(a>c){
				int temp=a;
				a=c;
				c=temp;
				temp=b;
				b=d;
				d=temp;
			}
			e[i]=new edge(a,b,c,d);
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i!=j&&e[i].x1>=e[j].x1&&e[i].x1<=e[j].x2){
					double y;
					if(e[j].x1==e[j].x2)
						y=(e[j].y1+e[j].y2)/2.0;
					else
						y=1.0*(e[i].x1-e[j].x1)*(e[j].y2-e[j].y1)/(e[j].x2-e[j].x1)+e[j].y1;
					if(y>e[i].y1){  //比较两个y的大小来判断优先度
						rudu[j]++;
						insert(i,j);
					}else{
						rudu[i]++;
						insert(j,i);
					}
				}
			}
		}
		Queue<Integer> q=new LinkedList<Integer>();
		for(int i=1;i<=n;i++)  //拓扑排序,初始入度为0的点入队列
			if(rudu[i]==0)
				q.add(i);
		while(!q.isEmpty()){
			int u=q.poll();
			for(int i=p[u];i!=-1;i=b[i].next){
				int v=b[i].v;
				if(--rudu[v]==0)
					q.add(v);
			}
			if(!q.isEmpty())
				System.out.print(u+" ");
			else
				System.out.println(u);
		}
		sc.close();
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值