• 拓扑排序小结


    例题一、 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
    ",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 ",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 "); 70 } 71 else 72 { 73 printf("%d ",sum); 74 } 75 } 76 77 return 0; 78 }



  • 相关阅读:
    牛客寒假算法集训 1
    求逆序数——树状数组
    牛客网 被3整除的子序列 区间dp
    SICNU 2019 winter training #2(codeforces #531 Div3)
    iOS 给已有的类添加属性.
    coredata实践
    IOS 数据库升级
    获取当前屏幕显示的viewcontroller
    ios 自顶一个view
    mac 修改文件夹权限.
  • 原文地址:https://www.cnblogs.com/1013star/p/9417781.html
Copyright © 2020-2023  润新知