hdu2647 - Reward (拓扑排序)

Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4248    Accepted Submission(s): 1293


Problem Description
Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.
The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.
 

Input
One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
 

Output
For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.
 

Sample Input
  
  
2 1 1 2 2 2 1 2 2 1
 

Sample Output
  
  
1777 -1
 

Author
dandelion
 

Source
                               简单拓扑
/*******************************
*
*   acm:   hdu-2647
*
*   title: Reward
*
*   time : 2014.9.14
*
*******************************/

//考察拓扑排序

/*
    求最小费用,每人最少费用是888,
    薪水是一层层分布的,即888第一层,8889第二层,.....
    因为知道的是"最少"的员工薪水,所以可以反向建图(正向不知道该人的薪水)
    e.g

       正序:
         890  889   888
        ① -> ② -> ③
                 ↗          888 + 889*2 + 890 = 3556
               ④ 889

      反序:
         890  889   888
        ① <- ② <- ③
                 ↙         888 + 889*2 + 890 = 3556
               ④ 889

*/

/*
    wa分析:1)要先判断其后驱原来的值是否小于用其的值+1;
            2)如果当前点邻接的点没有入栈即入度不为0(in!=0),
                也要分析当前点是否大于邻接点。
*/

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXEDGE 20001
#define MAXVEX 10001

typedef int Status;

/************  邻接矩阵结构  *************/
typedef struct EdgeNode  //边表结点
{
    int adjvex;              // 邻接点域,存储该顶点对应的下标
 //   int weight;              // 用于存储权值,对于非网图可以不需要
    struct EdgeNode *next;   // 链域,指向下一个邻接点
} EdgeNode;

typedef struct VertexNode   //顶点表结点
{
    int in;                 //顶点入度
    int data;               //顶点域,存储顶点信息
    EdgeNode *firstedge;    //边表头指针
} VertexNode, AdjList[MAXVEX];

typedef struct graphAdjList
{
    AdjList adjList;
    int numVertexes, numEdges;
} graphAdjList, *GraphAdjList;
/* **************************************** */


//构建邻接表
void CreateALGraph(GraphAdjList GL)
{
    int i;
    int V_a, V_b;
    EdgeNode *e;

    for (i = 1; i <= GL->numVertexes; i++)  //读入顶点信息,建立顶点表
    {
        GL->adjList[i].in = 0;
        GL->adjList[i].data = 888;
        GL->adjList[i].firstedge = NULL;  //将边表置为空表
    }

    for (i = 0; i < GL->numEdges; i++)  //建立边表
    {
        scanf("%d%d", &V_a, &V_b);

        e = (EdgeNode *)malloc(sizeof(EdgeNode));

        e->adjvex = V_a;              //邻接序号为V_a
        e->next = GL->adjList[V_b].firstedge;  //将当前顶点上的指向的结点指针赋值给e

        GL->adjList[V_b].firstedge = e;    //将当前顶点的指针指向e

        GL->adjList[V_a].in++;             //入度加1
    }

}

//拓扑排序,若GL无回路,则输出拓扑排序序列并返回1,若有回路返回0.
Status TopologicalSort(GraphAdjList GL, __int64 *num)
{
    EdgeNode *e;
    int i, k, gettop;
    int top = 0;    //用于栈指针下标
    int count = 0;  //用于统计输出顶点的个数
    int *stack;     //建栈将入度为0的顶点入栈

    *num = 0;

    stack = (int *)malloc(GL->numVertexes * sizeof(int ));

    for (i = 1; i <= GL->numVertexes; i++)
    {
        if (0 == GL->adjList[i].in)  //将入度为0的顶点入栈
        {
            stack[++top] = i;
        }
    }

    while (top != 0)
    {
        gettop = stack[top--];   //出栈

        *num += (__int64)GL->adjList[gettop].data;
        count++;                 //统计输出顶点数

        for (e = GL->adjList[gettop].firstedge; e; e = e->next)
        {
            //对此顶点弧表遍历
            k = e->adjvex;

            if (!(--GL->adjList[k].in))
            {
                stack[++top] = k;  //若为0则入栈,以便于下次循环输出

                if (GL->adjList[gettop].data >= GL->adjList[k].data)
                {
                    GL->adjList[k].data = GL->adjList[gettop].data + 1;
                }

            }
            else    //如果当前点邻接的点没有入栈
            {
                //判断当前点值是否大于邻接点值
                if (GL->adjList[gettop].data >= GL->adjList[k].data)
                {
                    GL->adjList[k].data = GL->adjList[gettop].data + 1;
                }
            }
        }
    }

    if (count < GL->numVertexes)
    {
        return ERROR;
    }
    else
    {
        return OK;
    }
}


int main()
{
    graphAdjList GL;
    int result;
    __int64 num;

    while (~scanf("%d%d", &GL.numVertexes, &GL.numEdges))
    {
        CreateALGraph(&GL);

        result = TopologicalSort(&GL, &num);

        if (result == TRUE)   //如果符合条件
        {
            printf("%I64d\n", num);
        }
        else
        {
            printf("-1\n");
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值