POJ - 3249 Test for Job (在DAG图利用拓扑排序中求最长路)

(点击此处查看原题)

题意

给出一个有n个结点,m条边的DAG图,每个点都有权值,每条路径(注意不是边)的权值为其经过的结点的权值之和,每条路径总是从入度为0的点开始,直至出度为0的点,问所有路径中权值最大者为多少,如下图,加粗的为权值最大者:

解题思路

这是在一个无起点、终点的图中的求最长路的问题,因此无法像一般的最长路问题那样求解。

首先,因为图中只存在点权,为了方便,我们一般将点权转化为边权:取每条边的权值为其终点的权值,将点权转化为边权。

然后,由于我们每条路径都是以入度为0的点开始,以出度为0的点结束,而且是求最大路,我第一想法就是AOV网中求事件的最晚完成时间,这两者是很相似的,不同的在于AOV网中有一个入度为0的源点和一个出度为0的汇点,而这个地方有多个入度为0的点和多个出度为0的点,不过实际的操作是完全一致的,都是利用拓扑排序的效果求最长路

为了方便理解,可以假设存在一个权值为0的点s向所有入度为0的点建边,然后把这个点当作起点,利用求拓扑序的时候,可以求出事件的最晚完成时间的效果,求其余各点到这个点的最长路,最后求出所有出度为0的点到s的最长路中的最大者,即为答案

代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>

#define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const ll inf = 1e18+10;
const ll mod = 1e9 + 7;
const int Max = 1e6 + 10;
const int Max2 = 3e2 + 10;

struct Edge
{
    int to,next;
    ll dis;
}edge[Max<<1];

int n, m;
ll val[Max];
int head[Max],tot;
int topo[Max],id;            //记录每个点的拓扑序
int d_in[Max],d_out[Max];    //记录每个点的入度和出度
ll dist[Max];                //距离源点的最大距离

int init()
{
    memset(head,-1,sizeof(head));
    tot = 0;
    memset(topo,0,sizeof(topo));
    id = 0;
    memset(d_in,0,sizeof(d_in));
    memset(d_out,0,sizeof(d_out));
}

void add(int u,int v,ll dis)
{
    edge[tot].to = v;
    edge[tot].dis = dis;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void topoSort()
{
    queue<int>q;                        //存储入度为0的点
    for(int i = 1;i <= n ;i ++)
    {
        if(d_in[i] == 0)
        {
            q.push(i);
            dist[i] = val[i];            //初始化
        }
    }
    while(!q.empty())
    {
        int u = q.front();q.pop();
        topo[u] = ++id;
        for(int i = head[u] ; i != -1 ; i = edge[i].next)
        {
            int v = edge[i].to;
            ll dis = edge[i].dis;
            if(!topo[v])
            {
                d_in[v] --;
                dist[v] = max(dist[v],dist[u] + dis);
                if(d_in[v] == 0)
                    q.push(v);
            }
        }
    }

}

int main()
{
#ifdef LOCAL
    //        freopen("input.txt", "r", stdin);
    //        freopen("output.txt", "w", stdout);
#endif
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i = 1;i <= n ;i ++)
            scanf("%lld",val+i);
        for(int i = 1, u, v ; i <= m ;i ++)
        {
            dist[i] = -inf;
            scanf("%d%d",&u,&v);
            d_out[u] ++;
            d_in[v]++;
            add(u,v,val[v]);        //以终点的权值作为边的权值
        }
        topoSort();
        ll max_dis = -inf;
        for(int i = 1;i <= n ;i ++)
        {
            if(d_out[i] == 0)            //只对出度为0的点进行判断
            {
                max_dis = max(max_dis,dist[i]);
            }
        }
        printf("%lld\n",max_dis);
    }
    return 0;
}
View Code 

转载于:https://www.cnblogs.com/winter-bamboo/p/11419268.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
POJ - 3616是一个题目,题目描述如下: 给定一组区间,每个区间有一个重,要求选择一些区间,使得这些区间的右端都小于等于k,并且重之和最大。请问最大的重和是多少? 解决这个问题的思是使用动态规划。首先,将区间按照左端从小到大进行排序。然后,定义一个dp数组,dp[i]表示右端小于等于i的所有区间所能得到的最大重。 接下来,遍历每一个区间,对于每个区间i,将dp[i]初始化为区间i的重。然后,再遍历i之前的每个区间j,如果区间j的右端小于等于k,并且区间j的重加上区间i的重大于dp[i],则更新dp[i]为dp[j]加上区间i的重。 最后,遍历整个dp数组,找到最大的重和,即为所求的答案。 下面是具体的代码实现: ```cpp #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct interval{ int start, end, weight; }; interval intervals[10005]; int dp[10005]; int n, m, k; bool compare(interval a, interval b) { if (a.start == b.start) { return a.end < b.end; } else { return a.start < b.start; } } int main() { while(~scanf("%d %d %d", &n, &m, &k)) { memset(dp, 0, sizeof dp); for (int i = 0; i < m; i++) { scanf("%d %d %d", &intervals[i].start, &intervals[i].end, &intervals[i].weight); } sort(intervals, intervals + m, compare); for (int i = 0; i < m; i++) { dp[i] = intervals[i].weight; for (int j = 0; j < i; j++) { if (intervals[j].end <= k && dp[j] + intervals[i].weight > dp[i]) { dp[i] = dp[j] + intervals[i].weight; } } } int maxWeight = 0; for (int i = 0; i < m; i++) { maxWeight = max(maxWeight, dp[i]); } printf("%d\n", maxWeight); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值