拓扑排序小结

例题一、 HDU-1285

有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表示即P1队赢了P2队。 
Output给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。 

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。 
Sample Input

4 3
1 2
2 3
4 3

Sample Output

1 2 4 3
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int maxn=100000;
 7 struct node{
 8     int to;
 9     int next;
10 }e[maxn];
11 int head[maxn],in[maxn],vis[maxn];
12 int cnt;
13 int m,n;
14 void init()
15 {
16     memset(head,-1,sizeof(head));
17     memset(in,0,sizeof(in));
18     cnt=0; 
19 }
20 int ans;
21 void add(int a,int b)
22 {
23     e[cnt].to=b;
24     e[cnt].next=head[a];
25     head[a]=cnt++;
26 }
27 void topu()
28 {
29     ans=0;
30     priority_queue<int,vector<int>,greater<int> >q;
31     for(int i=1;i<=n;i++)
32     {
33         if(in[i]==0)
34         {
35             q.push(i);
36         }
37     }
38     while(!q.empty())
39     {
40         int v=q.top();
41         vis[ans++]=v;
42         q.pop();
43         for(int i=head[v];i!=-1;i=e[i].next)
44         {
45             int u=e[i].to;
46             if(--in[u]==0)
47             {
48                 q.push(u);
49             }
50         }
51     }
52     for(int i=0;i<ans-1;i++)
53     {
54         printf("%d ",vis[i]);
55     }
56     printf("%d\n",vis[ans-1]);
57 }
58 int main()
59 {
60     while(~scanf("%d%d",&n,&m))
61     {
62         int a,b;
63         init();
64         for(int i=0;i<m;i++)
65         {
66             scanf("%d%d",&a,&b);
67             add(a,b);
68             in[b]++;
69         }
70         topu();
71     }
72 return 0;
73 }

例题二、HDU-2647   Reward

 题目大意:一个厂主要给员工发工资,底薪888,员工中有人a要求工资高于b,厂主想满足所有人的要求并且使自己花费最少。输出最少花销。

 

注意:①员工最大10000,且并不是所有人之间都有关系,所以不能用邻接矩阵,应用邻接表。

  ②输入a,b是a要求工资比b多,所以应从b向a连边。

  ③判断-1的情况不是只判断是否存在入度为0的点,还要判断是否存在环的情况。

  ④注意max判断。

 用邻接表存图的写法
1
#include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int maxn=10005; 8 int head[maxn],vis[maxn],in[maxn]; 9 int money[maxn]; 10 int m,n; 11 int tot=0,sum=0,ans=0; 12 struct node{ 13 int to; 14 int next; 15 }e[2*maxn]; 16 int cnt; 17 void init() 18 { 19 memset(head,-1,sizeof(head)); 20 memset(vis,0,sizeof(vis)); 21 memset(in,0,sizeof(in)); 22 memset(money,0,sizeof(money)); 23 cnt=0; 24 } 25 void add(int x,int y) 26 { 27 e[cnt].to=y; 28 e[cnt].next=head[x]; 29 head[x]=cnt++; 30 } 31 void topu() 32 { 33 queue<int>q; 34 for(int i=1;i<=n;i++) 35 { 36 if(in[i]==0) 37 q.push(i); 38 } 39 while(!q.empty()) 40 { 41 int v=q.front(); 42 sum+=money[v]; 43 q.pop(); 44 ans++; 45 for(int i=head[v];i!=-1;i=e[i].next) 46 { 47 if(--in[e[i].to]==0) 48 { 49 q.push(e[i].to); 50 money[e[i].to]=money[v]+1; 51 52 } 53 } 54 } 55 } 56 int main() 57 { 58 int a,b; 59 while(~scanf("%d%d",&n,&m)) 60 { 61 init(); 62 tot=0,sum=0,ans=0; 63 for(int i=1;i<=n;i++) 64 { 65 money[i]=888; 66 } 67 while(m--) 68 { 69 scanf("%d%d",&a,&b); 70 add(b,a); 71 in[a]++; 72 } 73 topu(); 74 if(ans!=n) 75 sum=-1; 76 printf("%d\n",sum); 77 } 78 return 0; 79 }
用vector存图的写法
1
#include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 const int maxn=21000; 8 int head[maxn],in[maxn],temp[maxn]; 9 int n,m,cnt,sum; 10 vector<int>v[maxn]; 11 int money[maxn]; 12 int topu() 13 { 14 for(int i=1;i<=n;i++) 15 { 16 money[i]=888; 17 } 18 queue<int>q; 19 sum=0; 20 for(int i=1;i<=n;i++) 21 { 22 if(in[i]==0) 23 q.push(i); 24 } 25 int cnt=0; 26 while(!q.empty()) 27 { 28 int tmp=q.front(); 29 cnt++; 30 sum+=money[tmp]; 31 q.pop(); 32 for(int i=0;i<v[tmp].size();i++) 33 { 34 in[v[tmp][i]]--; 35 if(!in[v[tmp][i]]) 36 { 37 q.push(v[tmp][i]); 38 money[v[tmp][i]]=money[tmp]+1; 39 } 40 } 41 } 42 if(cnt!=n) 43 return 1; 44 else 45 return 0; 46 } 47 int main() 48 { 49 int a,b; 50 int step,flag; 51 while(~scanf("%d%d",&n,&m)) 52 { 53 memset(in,0,sizeof(in)); 54 sum=0; 55 for(int i=0;i<maxn;i++) 56 { 57 v[i].clear(); 58 } 59 memset(in,0,sizeof(in)); 60 for(int i=1;i<=m;i++) 61 { 62 scanf("%d%d",&a,&b); 63 v[b].push_back(a); 64 in[a]++; 65 } 66 flag=topu(); 67 if(flag==1) 68 { 69 printf("-1\n"); 70 } 71 else 72 { 73 printf("%d\n",sum); 74 } 75 } 76 77 return 0; 78 }



posted @ 2018-08-04 10:36  *starry*  阅读(161)  评论(0编辑  收藏  举报