• [APIO2008]


    A.免费道路roads

    题意:给定n个点m条边的图,边有黑白颜色,求是否有一个生成树满足恰好有K条黑边,并输出方案。

    题解:先加白边,求出必须加的黑边,然后加黑边到K条,剩下的用白边填充。

    顺便说说,边权只有01的图,生成树的权值和可以取到任意的介于[MST,MBT]的任意值,其中MST表示最小生成树,MBT最大。

    我们可以发现MST和MBT的区别在与其中一些点,这些点与生成树联通的边可以选择0或者1,所以你可以把一些点的边替换,每次权值变化1,所以可以取到任意的权值.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 20000
    #define MM 100000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    struct edge{int from,to;}e[MM+5],e2[MM+5];
    int n,m,K,s[MN+5],cnt1=0,cnt2=0,q[MN+5],qx[MN+5],top,top2;
    
    int getfa(int x){return !s[x]?x:s[x]=getfa(s[x]);}
    
    int kruscal(edge*E,int num,int lim=MM)
    {
        top=0;
        for(int i=1;i<=num&&top<lim;i++)
        {
            int x=getfa(E[i].from),y=getfa(E[i].to);
            if(x!=y)
                s[x]=y,q[++top]=i;
        }
        return top;
    }
    
    int main()
    {
        n=read();m=read();K=read();
        for(int i=1;i<=m;i++)
        {
            int u=read(),v=read(),k=read();
            if(!k) e[++cnt1]=(edge){u,v};
            else  e2[++cnt2]=(edge){u,v};
        }    
        int num1=kruscal(e2,cnt2),num2=kruscal(e,cnt1);
        if(num2>K||cnt1<K||num1+num2!=n-1) return 0*puts("no solution");
        memset(s,0,sizeof(s));top2=top;
        for(int i=1;i<=top;i++) 
            qx[i]=q[i],s[getfa(e[q[i]].from)]=getfa(e[q[i]].to);
        if(kruscal(e,cnt1,K-num2)<K-num2) return 0*puts("no solution");
        for(int i=1;i<=top2;i++)printf("%d %d %d
    ",e[qx[i]].from,e[qx[i]].to,0);
        for(int i=1;i<=top;i++)
            printf("%d %d %d
    ",e[q[i]].from,e[q[i]].to,0);
        kruscal(e2,cnt2);
        for(int i=1;i<=top;i++)
            printf("%d %d %d
    ",e2[q[i]].from,e2[q[i]].to,1);
        return 0;
    }

    B.DNA

    给定一个长度为m的由ACGTN组成的字符串,定义大小关系A<C<G<T,你要把其中的N替换成ACGT的其中一个,满足最多有k个不下降的子序列的同时,求出第R大的字符串。

    $mleqslant 50000 Rleqslant 10^{12} kleqslant 10$

    题解:用f[i][j][k]表示第i到n位第i位是k,这部分分了j段的个数,这个容易转移,然后我们就一步步走呗。复杂度 O(16mk)

    #include<iostream>
    #include<cstdio>
    #define ll long long
    using namespace std;
    inline ll read()
    {
        ll x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    ll f[50005][12][5];
    int m,K,s[50005];ll R;
    char st[50005];
    char ch[4]={'A','C','G','T'};
    
    int main()
    {
        m=read();K=read();R=read();    
        scanf("%s",st+1);
        for(int i=1;i<=m;i++)
        {
            if(st[i]=='A') s[i]=1;
            else if(st[i]=='C') s[i]=2;
            else if(st[i]=='G') s[i]=3;
            else if(st[i]=='T') s[i]=4;
            else s[i]=0; 
        }
        if(s[m]) f[m][1][s[m]]=1;
        else f[m][1][1]=f[m][1][2]=f[m][1][3]=f[m][1][4]=1;
        for(int i=m-1;i;i--)
            for(int j=1;j<=K;j++)
                for(int k=1;k<=4;k++)
                    if(!s[i]||s[i]==k)
                        for(int l=1;l<=4;l++)
                        {
                            if(k<=l) f[i][j][k]+=f[i+1][j][l];
                            else f[i][j][k]+=f[i+1][j-1][l];
                        }
        for(int i=1;i<=m;i++)
            for(int k=1;k<=4;k++)
                for(int j=1;j<=K;j++)
                    f[i][j][k]+=f[i][j-1][k];
        for(int i=1,k=0;i<=m;i++)
            if(s[i]) 
            {
                printf("%c",st[i]);
                if(s[i]<k)--K;k=s[i]; 
            }
            else 
            {
                for(int j=1;j<=4;j++)
                    if(f[i][K-(j<k)][j]<R)
                        R-=f[i][K-(j<k)][j];
                    else
                    {
                        printf("%c",ch[j-1]);
                        if(j<k) --K;k=j;
                        break;
                    }
            }    
        return 0;
    }
  • 相关阅读:
    关于php中trim、ltrim和rtrim
    文件读取
    字典
    列表
    数据类型作业
    常用的数据类型
    字符串
    编码
    MVC 入门
    JavaScript 类型浅解
  • 原文地址:https://www.cnblogs.com/FallDream/p/apio2008.html
Copyright © 2020-2023  润新知