uva103 DAG最长路

题目大意:

有个n个m维的东西,要求你把它们垒高,第i个能放在第j个上的要求是对于i,j的所有m维都有a[i][k]<a[j][k](k>=0&&k<m),问最长能有多高,并输出方案。

分析:可以转化为DAG的最长路,对于第i个能放在第j个上建一条边,那么这个问题就成了求一个有向无环图的最长路。

dp[i]表示第i个结点开始的最长路则dp[i]可以转移到dp[j](存在i->j边)

方程为:dp[i]=max(dp[j]+1)(i->j边存在) 初始为dp[i]=1;

路径方案可以通过逆向输出。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <algorithm>
 6 #define maxn 40
 7 using namespace std;
 8 int n,m;
 9 int dp[maxn];//从i出发的最长路
10 vector<int>a[maxn];
11 bool judge(int x,int y){
12     vector<int>&la=a[x],&lb=a[y];
13     for(int i=0;i<m;++i){
14         if(la[i]<=lb[i])return false;
15     }
16     return true;
17 }
18 int dfs(int i){
19     int &ans = dp[i];
20     if(ans>0)return ans;
21     ans =1;
22     for(int j=0;j<n;++j){
23         if(i!=j&&judge(i,j)){
24             ans = max(ans,dfs(j)+1);
25         }
26     }
27     return ans;
28 }
29 int id;
30 void path(int u){
31     for(int i=0;i<n;++i){
32         if(judge(u,i)&&dp[i]==dp[u]-1){
33             path(i);break;
34         }
35     }
36     if(u!=id)printf("%d ",u+1);
37     else printf("%d
",u+1);
38 }
39 int main (){
40     int x;
41     while(scanf("%d%d",&n,&m)!=EOF){
42         for(int i=0;i<n;++i){
43             a[i].clear();
44             for(int j=0;j<m;++j){
45                 scanf("%d",&x);
46                 a[i].push_back(x);
47             }
48             sort(a[i].begin(),a[i].end());
49         }
50         memset(dp,0,sizeof(dp));
51         for(int i=0;i<n;++i)dfs(i);
52         int ans=0;
53         id=0;
54         for(int i=0;i<n;++i){
55             if(ans<dp[i]){
56                 ans=dp[i];
57                 id=i;
58             }
59         }
60         printf("%d
",ans);
61         path(id);
62     }
63 }
View Code
原文地址:https://www.cnblogs.com/shuzy/p/3690222.html