zoukankan      html  css  js  c++  java
  • POJ 3249DAG的单源最短路径

    题目链接 POJ3249

    题意

    给定几个带点权有向无环图,选一条从入度为0的起点走到出度为0的终点的路径,使得路径上的点权和最大。

    分析

    首先点权图转边权图

    直接对每条边赋值,值为终点的点权值。

    没有入度的点,添加一个顶点,连接一条有向边,使之边权等于该点点权。

    多个没有入度的点,只需添加一个顶点并与所有没有入度的点相连即可。

    然后求源点到终点的最远路径,使用拓扑排序,然后按排序后的序列更新最远路径。

    坑点:

    求的不是最短路而是最长路

    最远路径超int,要用LL

    代码

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <map>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #define MAX 1000007
    #define MAXN 100007
    #define MAXM 2000007
    #define MOD 1000000007
    using namespace std;
    typedef long long LL;
    struct Edge{
        int to;
        int w;
        int next;
    }edge[MAXM];
    int head[MAXN],tot,indegree[MAXN],
    n,m,s,pw[MAXN],outdegree[MAXN];
    LL dist[MAXN],ans;
    void addEdge(int u,int v,int w){
        edge[tot].to=v;
        edge[tot].next=head[u];
        edge[tot].w=w;
        head[u]=tot++;
        indegree[v]++;
        outdegree[u]++;
    }
    
    void topo(){
        int q[MAXN],iq=0;
        for(int i=0;i<=n;i++){
            if(indegree[i]==0) q[iq++]=i;
        }
        for(int i=0;i<iq;i++){
            for(int k=head[q[i]];k!=-1;k=edge[k].next){
                int t=edge[k].to;
                indegree[t]--;
                if(indegree[t]==0) q[iq++]=t;
            }
        }
        //cout<<iq<<endl;
        memset(dist, 0xc0,sizeof dist);
        //for(int i=0;i<MAXN;i++) dist[i]=-100000000000000;
        //cout<<dist[0]<<endl;
        dist[s]=0;
        for(int i=0;i<iq;i++){
            for(int k=head[q[i]];k!=-1;k=edge[k].next){
                int t=edge[k].to;
                dist[t]=max(dist[t], dist[q[i]]+edge[k].w);
                //cout<<dist[t]<<endl;
            }
        }
    }
    
    void init(){
        memset(head,-1,sizeof head);
        memset(indegree,0,sizeof indegree);
        memset(outdegree,0,sizeof outdegree);
        ans=0xc0c0c0c0c0c0c0c0;
        tot=0;
    }
    
    int main(){
        int u,v,w,q,x;
        while(scanf("%d%d",&n,&m)==2){
            init();
            for(int i=1;i<=n;i++){
                scanf("%d", &pw[i]);
            }
            for(int i=1;i<=m;i++){
                scanf("%d%d",&u,&v);
                addEdge(u, v, pw[v]);
            }
            for(int i=1;i<=n;i++){
                if(indegree[i]==0){
                    addEdge(0,i,pw[i]);
                }
            }
            s=0;
            topo();
            for(int i=1;i<=n;i++){
                if(outdegree[i]==0){
                    ans=max(ans, dist[i]);
                }
            }
            printf("%lld\n", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    T100——MENU按钮
    vue 打包问题
    Python: 什么是*args和**kwargs
    windows服务器下部署Apache+Flask+Mod_wsgi+Vue
    树莓派 端口被占用的解决方案
    mac 终端命令总结
    Home Assistant 发现小米设备
    树莓派基于Home Assistant 查询在网设备
    Linux 命令集合-vim
    mac上的hassbian 启动报错1
  • 原文地址:https://www.cnblogs.com/shuiming/p/7006651.html
Copyright © 2011-2022 走看看