zoukankan      html  css  js  c++  java
  • HDU 5811 Colosseo(拓扑排序+单调DP)

    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5811

     

    【题目大意】

      给出 一张单向图,现在将其划分成了两个部分,问划分之后的点是否分别满足按照一定序列排序后后面的点可以直接与前面的点相连,如果可以,从第二部分拆出几个点到第一部分仍然满足这个性质。

    【题解】

      对于第一问,我们可以拓扑排序判断,对于第二问,我们发现先在第一组的序列中找到第二组每个点的可插入位置,在第二组的位置序列中做最长不下降子序列就是答案。

    【代码】

    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <climits>
    #include <algorithm>
    using namespace std;
    const int N=1005,M=40000000;
    int n,m,mark[N],d[N],map[N][N],x,f[N][N],dp[N];
    vector<int> T1,T2; 
    char file[M],*F=file;
    void read(int&x){for(x=0;*F<48;F++);while(*F>47)x=x*10+*F++-48;}
    bool Topological(int t,vector<int>&ret){
        vector<int> v;
        for(int i=0;i<n;i++){d[i]=0;if(mark[i]==t)v.push_back(i);}
        for(int i=0;i<v.size();i++){
            for(int j=0;j<v.size();j++){
                if(map[v[i]][v[j]])d[v[i]]++;
            }
        }queue<int>Q;
        for(int i=0;i<v.size();i++)if(!d[v[i]])Q.push(v[i]);
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            ret.push_back(u);
            for(int i=0;i<v.size();i++){
                if(map[v[i]][u]){
                    --d[v[i]];
                    if(!d[v[i]])Q.push(v[i]);
                }
            }
        }if(ret.size()!=v.size())return 0;
        return reverse(ret.begin(),ret.end()),1; 
    }
    int main(){
        fread(file,1,M,stdin);
        while(1){
            read(n);read(m);
            if(m+n==0)return 0;
            for(int i=0;i<n;i++)for(int j=0;j<n;j++)read(map[i][j]);
            for(int i=0;i<n;i++)mark[i]=0;
            for(int i=0;i<m;read(x),mark[--x]=1,i++);
            T1.clear(); T2.clear();
            if(!Topological(1,T1)||!Topological(0,T2)){
                puts("NO");continue;
            }int ans=0;
            for(int i=0;i<T2.size();i++)f[m][i]=0;
            for(int i=m-1;i>=0;i--){
                for(int j=0;j<T2.size();j++)f[i][j]=f[i+1][j];
                for(int j=0;j<T2.size();j++){
                    if(map[T1[i]][T2[j]])f[i][j]=1;
                }
            }
            for(int i=0;i<T2.size();i++){
                dp[i]=INT_MIN; int t=m;
                for(int j=0;j<T1.size();j++){
                    if(map[T2[i]][T1[j]]){t=j;break;}
                }if(f[t][i])continue;
                dp[i]=1;
                for(int j=0;j<i;j++){
                    if(!f[t][j])dp[i]=max(dp[i],dp[j]+1);
                }ans=max(ans,dp[i]);
            }printf("YES %d
    ",ans);
        }return 0;
    }
  • 相关阅读:
    软件产品案例分析 ——华为软件开发云
    软件工程实践2017第一次作业
    软件工程实践2017结对第二次作业
    SDN第一次作业
    路由器工作原理
    Spring框架之springweb web源码完全解析
    Spring框架之springweb http源码完全解析
    Spring框架之jms源码完全解析
    Spring框架之AOP源码完全解析
    比特币里的计算机知识
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu5811.html
Copyright © 2011-2022 走看看