首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >POJ Test for Job(DAG上拓扑排序)

POJ Test for Job(DAG上拓扑排序)

作者头像
Ch_Zaqdt
发布2019-02-26 09:57:50
3010
发布2019-02-26 09:57:50
举报
文章被收录于专栏:Zaqdt_ACMZaqdt_ACM

题目链接:http://poj.org/problem?id=3249

       题意是给了n个点,m条边(单向边),然后每个点都有一个点权(存在负权),问从入度为0的点开始到出度为0的点,最大的权值和为多少。

       题目中说了这是一个DAG图(有向无环图),跑最长路的话会超时(spfa反向建边好像可以过),根据有向无环图的性质我们可以用拓扑排序来写,根据每条边的度数来选择边的顺序从而更新最长路的值。


AC代码:

// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 100005
#define maxm 1000005
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
struct Node{
  int to,next;
}Edge[maxm];
int head[maxn],num;
int n,m;
int depi[maxn], pre[maxn], depo[maxn];
ll dist[maxn];

void init(){
  for(int i=0;i<=n;i++){
    depi[i] = depo[i] = 0;
    head[i] = -1;
    dist[i] = -inf;
  }
  num = 0;
}

void add(int u,int v){
  Edge[num].to = v;
  Edge[num].next = head[u];
  head[u] = num ++;
}

void Topo(){
  queue<int> q;
  for(int i=1;i<=n;i++){
    if(depi[i] == 0){
      q.push(i);
      dist[i] = pre[i];
    }
  }
  while(!q.empty()){
    int u = q.front();
    q.pop();
    for(int i=head[u];i!=-1;i=Edge[i].next){
      int v = Edge[i].to;
      dist[v] = max(dist[v], dist[u] + pre[v]);
      if(--depi[v] == 0) q.push(v);
    }
  }
}

int main()
{
  while(~scanf("%d%d",&n,&m)){
    init();
    for(int i=1;i<=n;i++){
      scanf("%d",&pre[i]);
    }
    for(int i=0;i<m;i++){
      int u, v;
      scanf("%d%d",&u, &v);
      add(u, v);
      depi[v] ++;
      depo[u] ++;
    }
    Topo();
    ll ans = -inf;
    for(int i=1;i<=n;i++){
      if(depo[i] == 0) ans = max(ans, dist[i]);
    }
    printf("%lld\n", ans);
  }
  return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年01月27日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档