zoukankan      html  css  js  c++  java
  • CF 274D Lovely Matrix 拓扑排序,缩点 难度:2

    http://codeforces.com/problemset/problem/274/D

    这道题解题思路:

    对每一行统计,以小值列作为弧尾,大值列作为弧头,(-1除外,不连弧),对得到的图做拓扑排序即可.

    但本题数据较大,所以需要进行缩点,把相同数值的点缩在一起,成为一个新的大点,原先的小值列向大点连接,再由大点向大值列连接,可以减少边数

    举例来说,原本取值为1的有4个点,取值为2的有5个点,

    不缩点,就需要20条边

    缩点,只需要4+1+5=10条边

    (不过我还是觉得这个方法有点投机取巧??)

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    const int maxn=2e5+3;
    typedef pair<int,int> P;
    P a[maxn];
    int deg[maxn];
    bool used[maxn];
    int ans[maxn];
    vector <int >e[maxn];
    queue<int> que;
    int n,m,last,flast;
    
    int main(){
            scanf("%d%d",&n,&m);
            flast=m+1;
            for(int i=0;i<n;i++){
                    for(int j=0;j<m;j++){
                            scanf("%d",&a[j].first);
                            a[j].second=j+1;
                    }
                    sort(a,a+m);
    
                    last=flast;
                    for(int j=0;j<m;){
                            if(a[j].first==-1){j++;continue;}
                            int k=j;
                            while(a[k].first==a[j].first){
                                    e[a[k].second].push_back(last);
                                    deg[last]++;
                                    if(last>flast){
                                            e[last-1].push_back(a[k].second);
                                            deg[a[k].second]++;
                                    }
                                    k++;
                            }
                            last++;
                            j=k;
                    }
                    flast=last;
            }
            for(int i=1;i<=m;i++){
                   if(deg[i]==0){
                            que.push(i);
                   }
            }
            int len=0;
            while(!que.empty()&&len<m){
                    int s=que.front();que.pop();
                    if(used[s])continue;
                    used[s]=true;
                    if(s<=m)ans[len++]=s;
                    for(int i=0;i<e[s].size();i++){
                            int t=e[s][i];
                            if(!used[t]){
                                    deg[t]--;
                                    if(deg[t]==0){
                                            que.push(t);
                                    }
                            }
                    }
            }
            if(len<m){
                    puts("-1");
            }
            else for(int i=0;i<len;i++){
                    printf("%d%c",ans[i],i==len-1?'
    ':' ');
            }
            return 0;
    }
    

      

  • 相关阅读:
    C# 反射
    WPF之布局
    java网络编程中的BIO,NIO,AIO
    BIO的阻塞
    AttributeView的用法
    将linux文件中的tab更换为空格的三种方法
    安装nginx-ingress控制器,使用
    docker 搭建jenkins
    Manjaro 18.0.1 系统安装后值得看的两篇博客
    github创建自己的项目并进行推送
  • 原文地址:https://www.cnblogs.com/xuesu/p/4328706.html
Copyright © 2011-2022 走看看