zoukankan      html  css  js  c++  java
  • 某考试 T2 Seg

    Seg

    【问题描述】
    数轴上有n条线段,第i条线段的左端点是a[i],右端点是b[i]。
    Bob发现1~2n共2n个整数点,每个点都是某条线段的端点。
    这些线段有如下两类特点:
    1 x y,表示第x条线段和第y条线段相交(相交在这里指至少有一个公共点)
    2 x y,表示第x条线段在第y条线段的左边,且它们不相交。
    共有m个特点,每个特点都是如上两类之一。
    Bob想通过这些特点推理得到每条线段的端点。
    【输入格式】
    第一行两个正整数n,m
    接下来m行,每行三个正整数,描述线段的特点,格式见题目描述
    【输出格式】
    输出n行,第i行两个正整数,用空格隔开,分别是a[i]和b[i]
    可能有多种答案,输出字典序最小的答案。即先要求a[1]最小,若仍有多解再要求b[1]最小,若仍有多解再要求a[2]最小,若仍有多解再要求b[2]最小,若仍有多解再要求a[3]最小……
    如果无解输出“Wrong”(不输出引号)。
    【样例输入】
    3 2
    1 2 3
    2 1 3
    【样例输出】
    1 2
    3 5
    4 6
    【数据规模和约定】
    对于30%的数据, 1<=n,m<=10
    对于60%的数据, 1<=n,m<=1000
    对于100%的数据,1<=n,m<=100000

        题解在注释里有,要注意的就是一点,我们如果要求一个字典序最小的拓扑排序,正确的做法并不是尽量把小的塞到前面,

    而是把大的尽量塞到后面。

        这个要理解的话,就是如果我们尽量把小的噻前面,有可能一个优先级很高的是一个优先级很低的后继,这时候因为优先队列是优先出小的

    所以那个优先级很高的会很晚出来。

        而我们如果反着跑的话,是不会出现这种情况的,因为优先级低的会被挤到后面去。

    /*
        可以把每条线段的左右端点都看成一个变量。
    	设第i条线段的左右端点的变量为l[i],r[i]。
    	
    	条件1 => l[x]<r[y] && l[y]<r[x]
    	条件2 => r[x]<l[y]
    	
    	所以我们把大小关系拓扑建图一下,然后跑一个
    	优先编号小的线段端点,优先同一线段的左端点的
    	拓扑排序,这个用一下优先队列就行了。 
    */
    #include<bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define maxn 200005
    using namespace std;
    int ans[maxn],cnt=0,now,las;
    int n,id[maxn],m,opt,X,Y;
    priority_queue<int> q;
    vector<int> g[maxn];
    
    inline void topsort(){
    	for(int i=1;i<=now;i++) if(!id[i]) q.push(i);
    	int x,to;
    	while(!q.empty()){
    		x=q.top(),q.pop();
    		ans[x]=now--;
    		for(int i=g[x].size()-1;i>=0;i--){
    			to=g[x][i];
    			if(!(--id[to])) q.push(to);
    		}
    	}
    }
    
    int main(){
    	freopen("seg.in","r",stdin);
    	freopen("seg.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	now=n<<1;
    	
    	for(int i=1;i<=n;i++){
    		g[i*2].pb(i*2-1);
    		id[i*2-1]++;
    	}
    	
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%d",&opt,&X,&Y);
    		if(opt==1){
    			g[Y*2].pb(X*2-1),id[X*2-1]++;
    			g[X*2].pb(Y*2-1),id[Y*2-1]++;
    		}
    		else{
    			g[Y*2-1].pb(X*2);
    			id[X*2]++;
    		}
    	}
    	
    	topsort();
    	
    	if(now) puts("Wrong");
    	else for(int i=1;i<=n;i++){
    		printf("%d %d
    ",ans[i*2-1],ans[i*2]);
    	}
    	
    	return 0;
    }
    

      

  • 相关阅读:
    (转)java反射机制及简单工厂模式
    (转)JAVA反射机制理解
    (转)前缀、中缀、后缀表达式
    (转)java提高篇(四)-----理解java的三大特性之多态
    (转)java for循环的执行顺序和几种常用写法
    (转)JAVA堆栈操作
    POI 实现合并单元格以及列自适应宽度
    前端缓存支持的文件格式及请求方式
    freemarker在xml文件中遍历list数据
    freemarker在线编辑
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8508114.html
Copyright © 2011-2022 走看看