zoukankan      html  css  js  c++  java
  • [Sdwc] 线段

    线段有如下两类特点:
    1 x y, 表示第 x 条线段和第 y 条线段相交 (相交在这里指至少有一个公共点)
    2 x y,表示第 x 条线段在第 y 条线段的左边,且它们不相交。
    共有 m 个特点,每个特点都是如上两类之一。
    通过这些特点推理得到每条线段的端点。

    x与y相交说明a[x]<b[y]且a[y]<b[x]
    x在y左边说明b[x]<a[y]
    每条线段x还应满足a[x]<b[x]
    这相当于一个拓扑排序问题,小的数相当于安排在前面的任务
    输出的第i个数就是第i个任务,那么a[1]尽可能小说明任务1要尽可能早做,b[1]尽可能小说明任务2要尽可能早做……
    方法就是把DAG反向建边得到新图,在新图中求字典序最大的拓扑排序,再将这个排序反序输出就是满足要求的答案

    IMP:

    求一个字典序最小的拓扑排序,正确的做法并不是尽量把小的塞到前面,

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    using namespace std;
    const int N = 300500;
    int point[N],to[N],next[N],cc;
    int dui[N],dcc;
    int ru[N];
    int sc[N];
    int n,m;
    void AddEdge(int x,int y) {
        cc++;
        next[cc]=point[x];
        point[x]=cc;
        to[cc]=y;
        ru[y]++;
    }
    void Add(int x) {
        dcc++;
        int now=dcc;
        int next=now/2;
        while(next && dui[next]<x) {
            dui[now]=dui[next];
            now=next;
            next=now/2;
        }
        dui[now]=x;
    }
    int Del() {
        int val=dui[1];
        int now=1;
        int next=now*2;
        if(next+1<dcc && dui[next+1]>dui[next])
            next++;
        while(next<dcc && dui[next]>dui[dcc]) {
            dui[now]=dui[next];
            now=next;
            next=now*2;
            if(next+1<dcc && dui[next+1]>dui[next])
                next++;
        }
        dui[now]=dui[dcc];
        dcc--;
        return val;
    }
    int main() {
        int i,j;
        cin>>n>>m;
        while(m--) {
            int a,b,c;
            cin>>c>>a>>b;
            if(c==1) {
                AddEdge(a*2,b*2-1);
                AddEdge(b*2,a*2-1);
            } else
                AddEdge(b*2-1,a*2);
        }
        for(i=1; i<=n; i++)
            AddEdge(i*2,i*2-1);
        n*=2;
        for(i=1; i<=n; i++) {
            if(!ru[i])
                Add(i);
        }
        for(i=n; i>=1; i--) {
            if(!dcc) {
                printf("Wrong
    ");
                return 0;
            }
            int now=Del();
            int then=point[now];
            while(then) {
                int tox=to[then];
                ru[tox]--;
                if(!ru[tox])
                    Add(tox);
                then=next[then];
            }
            sc[now]=i;
        }
        for(i=1; i<=n; i++) {
            cout<<sc[i];
            if(i&1)
                cout<<' ';
            else
                cout<<endl;
        }
        return 0;
    }
  • 相关阅读:
    pku夏令营面试
    机器学习实验一SVM分类实验
    面试相关-转载-well,yzl——持续更新
    2715:谁拿了最多奖学金-poj
    1005:I Think I Need a Houseboat-poj
    2810:完美立方-poj
    2943:小白鼠排队-poj
    rem+媒体查询---移动端 设计稿以375
    微信小程序 + mock.js 实现后台模拟及调试
    一个div 实现纸张阴影效果
  • 原文地址:https://www.cnblogs.com/shandongs1/p/8588148.html
Copyright © 2011-2022 走看看