HDU_2647_Reward(拓扑排序)

Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4746    Accepted Submission(s): 1448

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

题意:老板要给n个员工发年终奖金,然后给出m个需求 (a,b),表示a的奖金要比b的多,然后呢,老板决定每个员工至少可以拿888元,现在老板总共至少需要发多少奖金。

如果满足不了就输出-1。

分析:拓扑排序问题。比第i个人奖金少的总人数有sum个,那么第i个人的奖金就是888+sum元。注意此题数据比较大,用邻接表存吧。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647

代码清单:

(1) vector实现

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;

const int maxv = 10000 +5;

int n,m;
int p,q;
bool judge;
int save[maxv];
int degree[maxv];
vector<int>graph[maxv];

void init(){
    memset(degree,0,sizeof(degree));
    for(int i=0;i<=n;i++) graph[i].clear();
}

int topSort(){
    int cnt=0;
    int sum=0;
    int q=888;
    while(cnt<n){
        int flag=0;
        for(int i=1;i<=n;i++){
            if(degree[i]==0){
                degree[i]=-1;
                save[flag++]=i;
                cnt++;
            }
        }
        if(!flag) return -1;
        sum+=q*flag; q++;
        for(int i=0;i<flag;i++){
            int u=save[i];
            for(int j=0;j<graph[u].size();j++){
                int v=graph[u][j];
                degree[v]--;
            }
        }
    }return sum;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        for(int i=0;i<m;i++){
            scanf("%d%d",&p,&q);
            judge=false;
            for(int j=0;j<graph[q].size();j++){
                if(graph[q][j]==p){
                    judge=true;
                    break;
                }
            }
            if(!judge){
                graph[q].push_back(p);
                degree[p]++;
            }
        }printf("%d\n",topSort());
    }return 0;
}

(2)静态邻接表(数组)

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;

const int maxv = 10000 + 5;
const int maxn = 20000 + 5;

struct Edge{
    int to,next;
}graph[maxn];

int n,m;
int p,q;
int index;
bool judge;
int save[maxv];
int head[maxn];
int degree[maxv];

void init(){
    index=1;
    memset(head,0,sizeof(head));
    memset(degree,0,sizeof(degree));
}

void add(int u,int v){
    graph[index].to=v;
    graph[index].next=head[u];
    head[u]=index++;
}

int topSort(){
    int cnt=0;
    int sum=0;
    int q=888;
    while(cnt<n){
        int flag=0;
        for(int i=1;i<=n;i++){
            if(degree[i]==0){
                degree[i]=-1;
                save[flag++]=i;
                cnt++;
            }
        }
        if(!flag) return -1;
        sum+=q*flag; q++;
        for(int i=0;i<flag;i++){
            int u=save[i];
            for(int j=head[u];j!=0;j=graph[j].next){
                int v=graph[j].to;
                degree[v]--;
            }
        }
    }return sum;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        for(int i=0;i<m;i++){
            scanf("%d%d",&p,&q);
            judge=false;
            for(int j=head[q];j!=0;j=graph[j].next){
                if(graph[j].to==p){
                    judge=true;
                    break;
                }
            }
            if(!judge){
                add(q,p);
                degree[p]++;
            }
        }printf("%d\n",topSort());
    }return 0;
}
时间: 2024-10-04 01:03:36

HDU_2647_Reward(拓扑排序)的相关文章

拓扑排序讲解

在这里我们要说的拓扑排序是有前提的 我们在这里说的拓扑排序是基于有向无环图的!!!. (⊙o⊙)…我所说的有向无环图都知道是什么东西吧.. 如果不知道,我们下面先来来说说什么是有向无环图. 所谓有向无环图,顾名思义是不存在环的有向图(至于有向图是什么不知道的在前面我们有一个图论讲解上都有). 点的入度:以这个点为结束点的边数. 点的出度:以这个点为出发点的边的条数. 拓扑序就是对于一个节点的一个排列,使得(u,v)属于E,那么u一定出现在v的前面.然而拓扑排序就是一个用来求拓扑序的东西. 对于左

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c    

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hdu1285(拓扑排序)

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

uva 10305 Ordering Tasks(拓扑排序)

拓扑排序,不用判断是否有环,dfs挺简单的 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> int map[105][105]; int visit[105]; int c[105]; int n,m,t; void dfs(int x) { visit[x] = 1; for(int i=1; i<=n; i++) { if(!visit[i]&&map[i][x]==1)

NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(忙碌的选课系统-拓扑排序注意重边)

D - 忙碌的选课系统 Time Limit: 10000 ms        Memory Limit: 65536 KB Submit Description 每学期末,都是万众瞩目的选课时间,由于人数过多,某学校的服务器常常被无数的学生挤的爆掉,这是,教务系统大人说,你们选个课都这么慢,居然还怪我们.于是,每次教务系统都会在服务器快要瘫痪前关闭它.在无数学生的强烈抗议下,教务系统妥协了,再给每个人一次机会,但他让我们用最快的方式决定该选的课程,选上后就退出. 这让大一学渣狗犯了难,在新的选

POJ1420 Spreadsheet(拓扑排序)注意的是超内存

Spreadsheet Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 617   Accepted: 290 Description In 1979, Dan Bricklin and Bob Frankston wrote VisiCalc, the first spreadsheet application. It became a huge success and, at that time, was the ki

拓扑排序之变量序列算法分析

拓扑排序之变量序列 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 题目描述: 假设有n个变量(1<=n<=26,变量名用单个小写字母表示),还有m个二元组(u,v),分别表示变量u小于v.那么,所有变量从小到大排列起来应该是什么样子的呢? 例如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b.尽管还有可能其他的可能,你只需找出其中的一个即可. 输入: 输入为一