两道拓扑排序的问题

多久没写东西了啊。。。。

两道拓扑排序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实现拓扑排序很方便~~)

代码:

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4 const int maxn = 100000 + 10;
 5 const int mod = 142857;
 6 int n, m, k;
 7 int num[maxn], in[maxn];
 8 vector<int> G[maxn];
 9
10 int solve(){
11     queue<int> q;
12
13     int ans = 0;
14     for( int i = 1; i <= n; ++i ){
15         if(!in[i]){
16             //cout << "i: " << i << endl;
17             q.push(i);
18         }
19     }
20
21     while(!q.empty()){
22         int u = q.front(); q.pop();
23         ans = ( ans + num[u] )%mod;
24
25         for( int i = 0; i < G[u].size(); ++i ){
26             int v = G[u][i];
27             in[v]--; num[v] = (num[u] + num[v])%mod;
28             if(!in[v])
29                   q.push(v);
30         }
31     }
32
33     return ans;
34 }
35
36 int main(){
37     scanf("%d%d%d", &n, &m, &k);
38
39     memset( num, 0, sizeof(num) );
40     int u, v;
41     for( int i = 0; i < k; ++i ){
42         scanf("%d", &u);
43         num[u]++;
44     }
45
46     memset( in, 0, sizeof(in) );
47     for( int i = 0; i < m; ++i ){
48         scanf("%d%d", &u, &v);
49         G[u].push_back(v); in[v]++;
50     }
51
52     int ans = solve();
53     printf("%d\n", ans);
54
55     return 0;
56 }

《hiho一下 第八十一周》

题目:http://hihocoder.com/contest/hiho81/problem/1

方法相同,建图稍微难点。。。

代码:

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4 const int maxn = 100000 + 10;
 5 const int mod = 142857;
 6 int n, m;
 7 vector<int> in[maxn];
 8 int s[maxn], ru[maxn], num[maxn];
 9 vector<int> e[maxn], G[maxn];
10
11 void init(){
12     for( int i = 0; i < maxn; ++i )
13       in[i].clear(), e[i].clear(), G[i].clear();
14     memset( s, 0, sizeof(s) );
15     memset( ru, 0, sizeof(ru) );
16     memset( num, 0, sizeof(num) );
17 }
18
19 void solve(){
20       queue<int> q;
21       for( int i = 0; i <= n; ++i ){
22           if(!ru[i])
23              q.push(i);
24       }
25
26       while(!q.empty()){
27             int u = q.front(); q.pop();
28             for( int i = 0; i < G[u].size(); ++i ){
29                   int v = G[u][i];
30                   ru[v]--, num[v] = (num[v] + num[u])%mod;
31                   if(!ru[v])
32                         q.push(v);
33             }
34       }
35 }
36
37 void print(){
38       printf("%d", num[1]);
39       for( int i = 2; i <= n; ++i ){
40             printf(" %d", num[i]);
41       }
42       printf("\n");
43 }
44
45 int main(){
46     //freopen("1.in", "r", stdin);
47     int T;
48     scanf("%d", &T);
49
50     while(T--){
51         init();
52         scanf("%d%d", &n, &m);
53
54         int u, v, k;
55         s[0] = -1, num[0] = 1;
56         for( int i = 0; i < m; ++i ){
57             scanf("%d", &u);
58             e[0].push_back(u);
59         }
60
61         for( int i = 1; i <= n; ++i ){
62             scanf("%d%d", &u, &k);
63             s[i] = u; in[u].push_back(i);
64             for( int j = 0; j < k; ++j ){
65                  scanf("%d", &u);
66                  e[i].push_back(u);
67             }
68         }
69
70         //build graph
71         for( int i = 0; i <= n; ++i ){
72             for( int j = 0; j < e[i].size(); ++j ){
73                 int sg = e[i][j];
74                 for( int p = 0; p < in[sg].size(); ++p ){
75                      int v = in[sg][p]; ru[v]++;
76                      G[i].push_back(v);
77                 }
78             }
79         }
80         //output();
81
82         solve();
83         print();
84     }
85
86     return 0;
87 }

时间: 2024-10-25 07:53:46

两道拓扑排序的问题的相关文章

两个拓扑排序的例题

#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

拓扑排序 - 确定比赛名次

Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输入有若干组,每组中的第一行为二个数N(1<=N<=500),M:其中N表示队伍的个数,M表示接着有M行的输入数据.接下来的M行数据中,每行也有两个整数P1,P2表示

hdu 4324 Triangle LOVE(拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4324 Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 3858    Accepted Submission(s): 1516 Problem Description Recently, scientists f

hdu1285(拓扑排序)

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

拓扑排序 POJ 2367

今天网易的笔试,妹的,算法题没能A掉,虽然按照思路写了出来,但是尼玛好歹给个测试用例的格式呀,吐槽一下网易的笔试出的太烂了. 就一道算法题,比较石子重量,个人以为解法应该是拓扑排序. 就去POJ找了道拓扑排序的题:POJ2367 直接上代码吧: #include<stdio.h> #include<string> #define clr(x) memset(x,0,sizeof(x)) int g[101][102]; int indegree[102]; int res[102]

关于拓扑排序的一些想法

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

UVALive 6264 Conservation --拓扑排序

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

hdu 1811 Rank of Tetris 【并查集+拓扑排序】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1811 分析: 很明显是道拓扑排序的题,有一点就是处理实力相等的问题: 可以用并查集把实力相等的组成一个集合. 说一下拓扑排序的性质: 1.如果入度为0的点大于1,则排序不唯一 2.如果排序的总数小于给定的数,则存在环路 献上代码: #include<stdio.h> #include<string.h> #include<algorithm> #include<ios

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),也就是说,每一条边代表着一个事件的发生,边的权值即为