• MicroRNA Ranking(Tehran2016)


    题意:给出m个n的全排列,求一个n的全排列,满足对于i<j,至少存在一半的全排列中,ai排在aj的前面,求字典序最小方案,或者是无解。

    (1)首先我们对 vis[ a[i] ][ a[j] ]++ ,求出a[i] 对 a[j] 的贡献。对vis[i][j] 和 vis[j][i]是否大于 一半 ,若大于就建立一条边,最后跑一边拓扑排序

    (2)比赛的时候,将大于j 的数插入 s[j] 的集合中,然后对每一位进行筛选,若当前位置的数没有比他大的,则当前位置的数就为该数,然后将这个数从s[i] (i = 1 - > n)中删除这个数

    依次循环,算的时间复杂度是0(k*n*n + n*n*log(n)),没想到超时了

    比赛结束后,改成用树状数组维护,AC  ....  没想到STL 时间复杂度真的是高

    拓扑排序 AC code

    #include <bits/stdc++.h>
     
    using namespace std;
     
    const int N = 1e3 + 10;
     
    int vis[N][N],a[N],in[N],ans[N],n;
     
    vector<int>edge[N];
     
    int topu()
    {
        int cont=0;
        priority_queue<int,vector<int>,greater<int> >Q;
        for(int i=1; i<=n; i++)
            if(in[i]==0)
                Q.push(i);
        while(!Q.empty())
        {
            int u=Q.top();
            Q.pop();
            cont++;
            ans[cont] = u;
            for(int i = 0 ;i < edge[u].size(); i++)
            {
                int v = edge[u][i];
                if(--in[v]==0)
                    Q.push(v);
            }
        }
        if(cont<n)
            return false;
        return true;
    }
    int main()
    {
        int m;
        while(~scanf("%d%d",&n,&m)&&n&&m)
        {
            memset(vis,0,sizeof(vis));
            memset(in,0,sizeof(in));
            for(int i = 1;i <= m;i++)
            {
                for(int j = 1;j <= n;j++)
                    scanf("%d",&a[j]);
                for(int j = 1;j <= n;j++)
                    for(int k = j+1;k <= n;k++)
                        vis[a[j]][a[k]]++;
            }
     
            for(int i = 1; i <= n;i++)
                for(int j = i + 1;j <= n;j++)
                {
                    if(vis[i][j] > vis[j][i])   edge[i].push_back(j),in[j]++;
                    else if(vis[i][j] < vis[j][i])  edge[j].push_back(i),in[i]++;
                }
     
            if(topu())
            {
                for(int i = 1;i <= n;i++)
                    printf("%d%c",ans[i],i == n?'
    ':' ');
            }
            else
                puts("No solution");
     
            for(int i = 1;i <= n;i++)
                edge[i].clear();
     
        }
        return 0;
    }

    set超时代码:

    #include <bits/stdc++.h>
     
    using namespace std;
     
    const int N = 1e3 + 10;
     
    int vis[N][N],a[N],vised[N];
    set<int>s[N];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m)&&n&&m)
        {
            for (int i=1;i<=n;i++)
            s[i].clear();
            memset(vis,0,sizeof(vis));
            memset(vised,0,sizeof(vised));
            for(int i = 1;i <= m;i++)
            {
                for(int j = 1;j <= n;j++)
                    scanf("%d",&a[j]);
                for(int j = 1;j <= n;j++)
                    for(int k = j+1;k <= n;k++)
                        vis[a[j]][a[k]]++;
            }
            for(int i = 1; i <= n;i++)
                for(int j = i + 1;j <= n;j++)
                {
                    if(vis[i][j] > m/2) vis[i][j] = 1,vis[j][i] = 0,s[j].insert(i);
                    else if(vis[j][i] > m/2) vis[j][i] = 1,vis[i][j] = 0,s[i].insert(j);
                    else    vis[i][j] = vis[j][i] = 0;
                }
     
            int ans[N],tot = 1;
     
            while(tot <= n)
            {
                int flag = 0,now = 0;
                for(int i = 1;i <= n;i++)
                {
                    if(!vised[i])
                    {
                        if(s[i].empty())
                        {
                            flag = 1;
                            now = i;
                            break;
                        }
                    }
                }
                if(!flag)   break;
                ans[tot] = now;
                vised[now] = 1;
                for(int i = 1;i <= n;i++)
                    if(s[i].find(now) != s[i].end())
                        s[i].erase(s[i].find(now));
                tot++;
            }
     
            if(tot <= n)    puts("No solution");
            else
            {
                for(int i = 1;i <= n;i++)
                    printf("%d%c",ans[i],i == n?'
    ':' ');
            }
        }
        return 0;
    }

    树状数组AC code:

    #include <bits/stdc++.h>
    #define IT set<int>::iterator
    
    using namespace std;
    
    const int N = 1e3 + 10;
    
    int vis[N][N],a[N],vised[N],c[N][N],n;
    
    
    int lowbit(int x){  return x&(-x);}
    void update(int pos,int x,int y)
    {
        while(x <= n)
        {
            c[pos][x] += y;
            x += lowbit(x);
        }
    }
    
    int query(int pos,int x)
    {
        int ans = 0;
        while(x)
        {
            ans += c[pos][x];
            x -= lowbit(x);
        }
        return ans;
    }
    int main()
    {
        int m;
        while(~scanf("%d%d",&n,&m)&&n&&m)
        {
            memset(c,0,sizeof(c));
            memset(vis,0,sizeof(vis));
            memset(vised,0,sizeof(vised));
            for(int i = 1;i <= m;i++)
            {
                for(int j = 1;j <= n;j++)
                    scanf("%d",&a[j]);
                for(int j = 1;j <= n;j++)
                    for(int k = j+1;k <= n;k++)
                        vis[a[j]][a[k]]++;
            }
            for(int i = 1; i <= n;i++)
                for(int j = i + 1;j <= n;j++)
                {
                    if(vis[i][j] > vis[j][i])   vis[i][j] = 1,vis[j][i] = 0,update(j,i,1);
                    else if(vis[j][i] > vis[i][j]) vis[j][i] = 1,vis[i][j] = 0,update(i,j,1);
                    else vis[i][j] = vis[j][i] = 0;
                }
    
            int ans[N],tot = 1;
    
            while(tot <= n)
            {
                int flag = 0,now = 0;
                for(int i = 1;i <= n;i++)
                {
                    if(!vised[i])
                    {
                        if(!query(i,n))
                        {
                            flag = 1;
                            now = i;
                            break;
                        }
                    }
                }
                if(!flag)   break;
                ans[tot] = now;
                vised[now] = 1;
                for(int i = 1;i <= n;i++)
                {
                    if(vis[now][i])
                        update(i,now,-1);
                }
                tot++;
            }
    
            if(tot <= n)    puts("No solution");
            else
            {
                for(int i = 1;i <= n;i++)
                    printf("%d%c",ans[i],i == n?'
    ':' ');
            }
        }
        return 0;
    }
  • 相关阅读:
    源码分析shiro认证授权流程
    shiro功能模块
    Java NIO(New I/O)的三个属性position、limit、capacity
    阻塞和非阻塞,同步和异步 总结
    小白科普:Netty有什么用?
    【异常】SSM整合quartz之org.quartz.impl.JobDetailImpl----ClassNotFoundException
    笔记本键盘字母按出来的都是快捷键
    eclipse egit提交方法
    oracle批量insert
    CAS Client 3.2.1 配置详解
  • 原文地址:https://www.cnblogs.com/lemon-jade/p/9600802.html
Copyright © 2020-2023  润新知