两个拓扑排序的例题

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 6010;
const int MAXM = 5000000;

struct line
{
    int id;
    int x1, y1;
    int x2, y2;
    line(int _id, int _x1, int _y1, int _x2, int _y2):id(_id),x1(_x1),y1(_y1),x2(_x2),y2(_y2) {}
};

struct edge
{
    int v, next;
} e[MAXM];

vector<line> lim;

int p[MAXN], eid;
int indegree[MAXN];

int N;

void init()
{
    memset(p, -1, sizeof(p));
    memset(indegree, 0, sizeof(indegree));
    eid = 0;
}

void insert(int u, int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}

int direction(line a, line b)
{
    if ((a.x1<b.x1 && a.x2<b.x1) || (b.x1<a.x1 && b.x2<a.x1)) return 0;
    if (a.x1==a.x2)
        if(max(a.y1,a.y2)<max(b.y1,b.y2)) return 1;
        else return 2;
    if (b.x1==b.x2)
        if(max(b.y1,b.y2)<max(a.y1,a.y2)) return 2;
        else return 1;
    if (a.x1 <= b.x1)
    {
        if(a.x2 <= b.x2)
        {
            double t=b.y1+1.0*(b.y2-b.y1)*(a.x2-b.x1)/(b.x2-b.x1);
            //cout<<a.id<<" "<<b.id<<"cao"<<a.y2<<" "<<t<<endl;
            if (a.y2 < t) return 1; // a->b
            else return 2; // b->a;
        }
        else
        {
            double t=a.y1+1.0*(a.y2-a.y1)*(b.x2-a.x1)/(a.x2-a.x1);
            if (b.y2 < t) return 2;
            else return 1;
        }
    }
    else
    {
        if(a.x2 <= b.x2)
        {
            double t=b.y1+1.0*(b.y2-b.y1)*(a.x2-b.x1)/(b.x2-b.x1);
            if (a.y2 < t) return 1; // a->b
            else return 2; // b->a;
        }
        else
        {
            double t=a.y1+1.0*(a.y2-a.y1)*(b.x2-a.x1)/(a.x2-a.x1);
            if (b.y2 < t) return 2;
            else return 1;
        }
    }
}

void build()
{
    init();
    int num = lim.size();
    for (int i = 0; i < num-1; i++)
    {
        for (int j = i+1; j < num; j++)
        {int rel = direction(lim[i], lim[j]);
            //printf("%d %d, %d\n", lim[i].id, lim[j].id, rel);
            switch(rel)
            {
            case 0:
                break;
            case 1:
                insert(lim[i].id, lim[j].id);
                indegree[ lim[j].id ]++;
                break;
            case 2:
                insert(lim[j].id, lim[i].id);
                indegree[ lim[i].id ]++;
                break;
            }
        }
    }
}

void topo()
{
    //queue<int> q;
    priority_queue<int> q;
    for (int i = 1; i <= N; i++)
    {
        if (indegree[i] == 0)
        {
            q.push(i);
        }
    }
    while(!q.empty())
    {
        //int now = q.front();
        int now = q.top();
        printf("%d ", now);
        q.pop();
        for (int i = p[now]; i != -1; i = e[i].next)
        {
            int v = e[i].v;
            indegree[v]--;
            if (!indegree[v])
            {
                q.push(v);
            }
        }
    }
}

int main()
{
    scanf("%d", &N);
    lim.clear();
    for (int i = 0; i < N; i++)
    {
        int x1,y1,x2,y2;
        scanf("%d%d%d%d", &x1,&y1,&x2,&y2);
        if(x1>x2)
        {
            swap(x1,x2);
            swap(y1,y2);
        }
        lim.push_back(line(i+1,x1,y1,x2,y2));
    }
    build();
    topo();
}

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>

#define MAXN 10005
#define MAXM 20005
using namespace std;
struct edge
{
    int v,next;
} e[MAXM];
int p[MAXN],eid;
int indegree[MAXN];
int n,m,get_point=0,res;
void init()
{
    memset(p,-1,sizeof(p));
    memset(indegree,0,sizeof(indegree));
    eid=0;
}

void insert(int u,int v)
{
    e[eid].v=v;
    e[eid].next=p[u];
    p[u]=eid++;
    indegree[v]++;
}

int topo()
{
    int ans=0;
    queue<int> q;
    queue<int> cost;

    for(int i=1; i<=n; i++)
    {
        if(!indegree[i])
        {
            q.push(i);
            cost.push(100);
        }
    }

    while(!q.empty())
    {
        get_point++;
        int now=q.front();
        q.pop();
        int co=cost.front();
        cost.pop();
        ans+=co;

        for(int i=p[now]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            indegree[v]--;
            if(!indegree[v])
            {
                q.push(v);
                cost.push(co+1);
            }
        }
    }
    return ans;
}

int main()
{
    int a,b;
    scanf("%d%d",&n,&m);
    init();
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&a,&b);
        insert(b,a);
    }
    res=topo();
    if(get_point==n) printf("%d\n",res);
    else printf("Unhappy!\n");
    return 0;
}
时间: 2024-11-05 22:14:55

两个拓扑排序的例题的相关文章

两道拓扑排序的问题

多久没写东西了啊.... 两道拓扑排序Liv.1的题....方法是一样的~~ <拓扑排序·二> 题目:http://hihocoder.com/contest/hiho81/problem/1 一个电脑网路,单向边,如果存在边u->v,那么u的病毒会感染到v. 要点,不存在环!那么如果u的入度=0的话,那么u中的病毒数不会再变化. 想到拓扑排序.不断删去入度为0的点.每次删去节点u,如果存在u->v,那么病毒数 num[v] += num[u].问题解决. (用queue实现拓扑排

hdu3342(Legal or Not)----- 学习拓扑排序的好例题

经典拓扑排序 点击打开链接 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exch

hdu1285(拓扑排序)

这道题要求没有输赢关系的两个元素必须按照升序输出,有输赢关系的,赢得在输的前面,所以用队列或者栈来降低时间复杂度的优化过的拓扑排序会出错. 比如这组输入 5 3 1 2 2 3 4 5 至少我写的两种拓扑排序都wa了.但是不用队列或者栈来优化的话, 1.每次都从头至尾扫描一遍,找到一个没标记过的节点, 2.将它标记 3.然后删除从它出来的每条边. 重复这三个操作,加标记的次序,就是题目要的答案. 下面的代码中用到了队列,但只是用来保存答案而已.并没有用它优化的意思. #include <iost

关于拓扑排序的一些想法

前几天数据结构课上老师给我们留了一道思考题:如何求出拓扑排序的所有可能路径.说实话,自己的第一感觉就是深搜DFS,但是到最后又被自己推翻了,本来周三的时候想到了一个算法,后来又被自己推翻了.在BestCoder群里问了几个大神,他们也没给出什么好的方法,印象深刻的是有人说我问这种题有意义吗,问得我竟然无法反驳,也是,大多数的人总是要为自己的无知做一些辩解. 后来整理了一下自己之前所想的,虽然有很大一个漏洞(这就是我推翻我算法的原因),不过自己所想到的算法自己都用代码实现了,也算是一件成功的事情.

UVALive 6264 Conservation --拓扑排序

题意:一个展览有n个步骤,告诉你每一步在那个场馆举行,总共2个场馆,跨越场馆需要1单位时间,先给你一些约束关系,比如步骤a要在b前执行,问最少的转移时间是多少. 解法:根据这些约束关系可以建立有向边,可以看出是拓扑排序问题,问题是怎样拓扑排序. 进行两次拓扑排序,分别建立两个集合,一个放场馆1举行的步骤,一个放场馆2的,然后第一次从场馆1开始进行拓扑排序,每次一个场馆取完后看另一个场馆是否有步骤要执行,有则执行,然后将度数变为0的压入队列,如此往复.第二次从场馆2开始进行.得出的最小值为答案.

hdu Instrction Arrangement(关键路径 + 拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意: 5 2                     //5个进程(编号从 0 开始)需要被执行,有2个约束条件, 问全部执行完成的最短时间. 1 2 1                   //1号要在2号进程执行完成的后一纳秒执行 3 4 1 Sample Output 2 关键路径: 基于AOE网(Activity On Edge),也就是说,每一条边代表着一个事件的发生,边的权值即为

ZZUOJ 1199 大小关系(拓扑排序,两种方法_判断入度和dfs回路判断)

1 /* 2 这道题如果按照度为0的节点来判断的时候,将度为0的节点和其相连的节点(度数并减去1) 3 从图中去掉,如果度为0的节点的个数为0个但是图中的节点没有都去掉的 时候那么说明 4 出现了回路!用这种方法必须将重边去除掉! 5 6 所以推荐用dfs方式进行判断!这种方式还是比较直观的! 7 */ 8 #include<iostream> 9 #include<cstring> 10 #include<cstdio> 11 #include<algorith

数据结构:图论:拓扑排序! 两种方法!

拓扑排序:(1)由偏序变成全序的过程!直观的说,偏序指集合中仅有部分成员之间可比较!而全序指集合中全体成员之间均可比较! (2)将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前. 数据结构中进行拓扑排序的方法: 方法一: (1)在有向图中选一个没有前驱的顶点且输出之! (2)从图中删除该顶点和所有以它为尾的弧. (3)重复上述两部,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止.后一种情况说明有向图中存在环! 代码: #

有向无环图(DAG)拓扑排序的两种方法

如下图的DAG: 第一种: (1)从AOV网中选择一个没有前驱的顶点并且输出它: (2)从AOV网中删除该顶点,并且上去所有该顶点为尾的弧: (3)重复上述两步,直到全部顶点都被输出,或者AOV网中不存在没有前驱的顶点. 第二种: 使用深度优先搜索(DFS),并标记每一个节点的第一次访问(pre)和最后一次访问时间(post),最后post的逆序就是DAG的拓扑排序,其实也是节点在进行DFS搜索时,出栈的逆序就是拓扑排序. 拓扑序列的结果有: (1) c++,高等数学,离散数学,数据结构,概率论