拓扑排序

P1113 杂务

输入格式

第1行:一个整数 \(n\ (3 \le n \le 10{,}000)\),必须完成的杂务的数目;

\(2\)\(n+1\) 行,每行有一些用空格隔开的整数,分别表示:

  • 工作序号(保证在输入文件中是从 \(1\)\(n\) 有序递增的);
  • 完成工作所需要的时间 \(len\ (1 \le len \le 100)\)
  • 一些必须完成的准备工作,总数不超过 \(100\) 个,由一个数字 \(0\) 结束。有些杂务没有需要准备的工作只描述一个单独的 \(0\)

保证整个输入文件中不会出现多余的空格。

输出格式

一个整数,表示完成所有杂务所需的最短时间。

输入输出样例 #1

输入 #1

7
1 5 0
2 2 1 0
3 3 2 0
4 6 1 0
5 1 2 4 0
6 8 2 4 0
7 4 3 5 6 0

输出 #1

23

由于要先做某事,才能接着完成另一件事,所以采用拓扑排序。我们对输入进行编码:

for(int i=1;i<=n;i++)
    {
      int a,b,c;
      scanf("%d%d%d",&a,&b,&c);
      t[i]=b;
      while(c)
      {
        degree[a]++;            //e[c]表示以c为前驱的节点
        e[c].push_back(a);        //这样凡是前面多一个前驱的节点,入度都要+1
        scanf("%d",&c);
      }
    }

再进行bfs:

void bfs()
{
  queue<int> q;
  for(int i=1;i<=n;i++)
  {
    f[i]=t[i];                                                                                                                                                                                                                                                                                                                    
    if(degree[i]==0)       //先将入度为0的节点直接入队
      q.push(i);       
  }
  while(!q.empty())
  {
    int u=q.front();
    q.pop();
    for(int i=0;i<e[u].size();i++)
    {
      int v=e[u][i];
      degree[v]--;                     //由于u已经离队,所以节点v的入度就减少
      f[v]=max(f[v],t[v]+f[u]);       
      if(!degree[v]) 
        q.push(v);
    }
  }
}

posted @ 2025-03-01 10:54  _窗帘  阅读(14)  评论(0)    收藏  举报