zoukankan      html  css  js  c++  java
  • CF-721C DAG图拓扑排序+费用DP

    比赛的时候写了个记忆化搜索,超时了。

    后来学习了一下,这种题目应该用拓扑排序+DP来做。

    dp[][]保存走到[第i个节点][走过j个点]时所用的最短时间。

    pre[][]用前驱节点求路径

    然后遍历一下dp[n][],求满足t范围的最大下标。

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #define N 5050
    #define INF 1000000200
    //#define LL long long int
    using namespace std;
    int n,m,sum,cnt,flag,t;
    int deg[N];
    vector<int> g[N],f[N];//保存后继节点
    int dp[N][N],pre[N][N];//保存走到第i个点,走过j个点时所用时间
    struct cmp
    {
        bool operator()(int a,int b)
        {
            return a>b;
        }
    };
    void topoSort()
    {
        priority_queue<int,vector<int>,cmp> q;
        for(int i=1;i<=n;i++)
            if(deg[i]==0)
                q.push(i),deg[i]--;
        while(!q.empty())
        {
            //if(q.size()>1) 可用于判断是否充分排序。
            //如果有多个入度为0的同时入队,说明他们之间没有明确的排序条件。
            int u=q.top();
            q.pop();
            sum--;//可用于判断是否有冲突,如果有冲突,就会导致两者或者已上的节点入度无法降为0
            for(int i=0;i<g[u].size();i++)
            {
                int e=g[u][i];
                deg[e]--;
                for(int j=2;j<=n;j++)
                {
                    //cout<<dp[u][i]<<' '<<e<<endl;
                    if(dp[e][j]>dp[u][j-1]+f[u][i])
                        dp[e][j]=dp[u][j-1]+f[u][i],pre[e][j]=u;
                }
            }
            for(int i=1;i<=n;i++)
                if(deg[i]==0)
                    q.push(i),deg[i]--;
        }
    }
    void ini()
    {
        for(int i=0;i<=n;i++)
            deg[i]=0,flag=0,g[i].clear(),f[i].clear();
        cnt=0,sum=n;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                dp[i][j]=t+100,pre[i][j]=-1;
        dp[1][1]=0;
    }
    void add(int u,int v,int fe)
    {
        deg[v]++;
        g[u].push_back(v);
        f[u].push_back(fe);
    }
    int main() {
        //cin.sync_with_stdio(false);
        scanf("%d%d%d",&n,&m,&t);
            ini();
            for(int i=0;i<m;i++)
            {
                int u,v,fe;
                scanf("%d%d%d",&u,&v,&fe);
                add(u,v,fe);
            }
            //cout<<dp[1][2]<<endl;
            topoSort();
            int Maxp=-1;
            for(int i=1;i<=n;i++)
            {
                if(dp[n][i]<=t)
                    Maxp=i;//求最大合法经过点数
            }
            stack<int> ss;
            int pos=n,lef=Maxp;
            cout<<Maxp<<endl;
            while(pos!=-1)
            {
                ss.push(pos);
                pos=pre[pos][lef],lef--;
            }
            //ss.push(1);
            while(ss.size()>1)
                cout<<ss.top()<<' ',ss.pop();
            cout<<ss.top()<<endl;
            ss.pop();
        
        return 0;
    }
  • 相关阅读:
    ubuntu 如何 su 到 root(作为 root 用户操作)
    centos6.5 redis 安装配置及java调用
    springmvc 国际化
    springmvc 整合数据验证框架 jsr
    springmvc 整合shiro
    centos 6.5 安装mysql
    hive 报错 java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
    centos 关闭防火墙
    client.HConnectionManager$HConnectionImplementation: Can't get connection to ZooKeeper: KeeperErrorCode = ConnectionLoss for /hbase
    fms +fme 视频直播
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/5957498.html
Copyright © 2011-2022 走看看