hdu 2647 Reward

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=2647

拓扑排序方法如下:

(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.

(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.

(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.

第一次做拓扑排序,有几点要说明一下:

1.vector是一个容器,可以动态分配内存,存储方式是线性的,他有几个常用的函数:

s[b].push_back(a):把a放到b这一数组后面;

s[b].size():测量在s[b]后面放了几个元素。

2.pair中的make_pair(x,y)可以把两个数据组合成一个,在函数需要返回两个整数的时候也可以用这个函数。

3.注意输出的结果要用长整形。

源代码:

 1 #include <iostream>
 2 #include<queue>
 3 #include<vector>
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6 #include<cstring>
 7 #define maxn 10005
 8 using namespace std;
 9 struct {int id;} point[maxn];//节点在排序中所处位次
11 typedef pair<int,int>Pair;
12 vector<int>map[maxn]; //记录拓扑排序的方式
13 queue<Pair>q;
14 int m,n;
15 __int64 ans;
16 int from[maxn];
17 bool topo(){
18     int count=0;
19   for(int i=1;i<=n;i++){
20     if(from[i]==0){
21       q.push(make_pair(i,0));
22       count++;
23     }
24   }
25   while(!q.empty()){
26     int x=q.front().first;
27     int y=q.front().second;
28     q.pop();
29     for(int i=0;i<map[x].size();i++){
30       int z=map[x][i];
31       point[z].id=max(point[z].id,y+1);
32       from[z]--;
33       if(from[z]==0){
34       q.push(make_pair(z,point[z].id));
35       count++;
36       }
37     }
38   }
39   ans=0;
40   for(int i=1;i<=n;i++)
41     ans+=point[i].id;
42     if(count==n)return true; //不存在环
43     else return false;
44 }
45 
46 int main()
47 {
48   int a,b;
49   while(scanf("%d %d",&n,&m)!=EOF){
50       memset(from,0,sizeof(from)); //入度
51       for(int i=1;i<=n;i++){
52         point[i].id=0;
53         map[i].clear(); //注意清除上一次的记录
54               }
55     for(int i=1;i<=m;i++){
56       scanf("%d %d",&a,&b);
57       map[b].push_back(a);  //注意不要放反了
58       from[a]++;
59     }
60     if(topo())
61       printf("%I64d\n",ans+=888*n);
62     else
63       printf("-1\n");
64 
65 
66   }
67     return 0;
68 }

 

转载于:https://www.cnblogs.com/xiaoze-yj/p/3255476.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值