• lxs Contest #120 2020.1.19


    https://file.floj.tech/export/nYGAiM5E4Y4e15467bb2

    t1 图

    【题意】

    给定无向连通图,判断它是否能被适中颜色染成使每个边所连的两个点颜色不同。如果不能则找出删去后原图仍然连通的奇环。

    【题解】

    先找出原图一颗生成树,黑白染色使相邻的点颜色不同。在剩下的边上如果是一个二分图,则可以,否则有奇环。dfs并将沿途点再次黑白染色。如果染不了力则向上跳父亲知道跳到对面的点,这就是奇环。否则将染好的色输出即可。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+5;
    bool pan;
    int n,m,last[N],last3[N],size3,st[N],top,size=1,ans[N],ge,last2[N],size2,siz,fa[N],ans1;
    int book[N],ji[N<<1];
    struct pigu
    {
        int dao,ne;
    }a[N<<1],b[N<<1],c[N<<1];
    inline void lingjiebiao2(int x,int y)
    {
        b[++size2].dao=y;
        b[size2].ne=last2[x];
        last2[x]=size2;
    }
    inline void lingjiebiao(int x,int y)
    {
        a[++size].dao=y;
        a[size].ne=last[x];
        last[x]=size;
    }
    inline void lingjiebiao3(int x,int y)
    {
        c[++size3].dao=y;
        c[size3].ne=last3[x];
        last3[x]=size3;
    }
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    inline void dfs1(int now)
    {
        for(int i=last[now];i;i=a[i].ne)
        {
            if(book[a[i].dao]==0)
            {
                book[a[i].dao]=1;
                ji[i]=ji[i^1]=1;
                ans[a[i].dao]=ans[now]^1;
                dfs1(a[i].dao);
            }
        }
    }
    inline void dfs2(int now)
    {
        for(int i=last3[now];i;i=c[i].ne)
        {
            if(book[c[i].dao]==book[now])
            {
                cout<<"B ";
                int hu=now;ans1=1;ans[ans1]=c[i].dao;
                while(hu!=c[i].dao)
                {
                    ans1++;
                    ans[ans1]=hu;
                    hu=fa[hu];
                }
                cout<<ans1<<" ";
                for(int j=1;j<=ans1;j++) cout<<ans[j]<<" ";
                pan=1;
                return;
            }
            if(book[c[i].dao]==0x3f3f3f3f)
            {
                fa[c[i].dao]=now;
                book[c[i].dao]=book[now]^1;
                dfs2(c[i].dao);
                if(pan==1) return;
            }
        }
    }
    int main()
    {
    //    freopen("g.in","r",stdin);
    //    freopen("g.out","w",stdout); 
        n=read();m=read();
        for(int i=1,x,y;i<=m;i++)
        {
            x=read();y=read();
            lingjiebiao(x,y);
            lingjiebiao(y,x);
        }book[1]=1;
        dfs1(1);
        for(int i=1;i<=n;i++)
            for(int j=last[i];j;j=a[j].ne)
                if(ji[j]==0) lingjiebiao3(i,a[j].dao);
        memset(book,0x3f3f3f3f,sizeof(book));
        for(int i=1;i<=n;i++)
        {
            if(book[i]==0x3f3f3f3f)
                book[i]=0,dfs2(i);
            if(pan==1) return 0;
        }
        cout<<"A ";
        for(int i=1;i<=n;i++)
            cout<<((ans[i]<<1)|book[i])+1<<" ";
        return 0;
    }
    View Code

    t2  数列

    前50分很好搞。

    对于后50分,先询问8次,每次询问形如{1,(10^{49})} ,这样我们就得到了8个 数的后头49位,我们只要求出了另一个数的后8位即可求出这8个数及另一个数。

    所以在询问两次{0,1,0,(10^{8}),0,(10^{16})\,……}。即可得出这些数的后8位。

    要手写高精度减法,码量大,莫得代码。

    t3 走路

    【题意】

    有n个地点,x点行动力,起点为0,餐馆地点为1-n,到一个餐馆可以选择吃a[i]点食物,在吃了k点食物后每走一步就需要(k+1)的行动力,求在可以回到起点的情况下最多可以吃好多点食物。

    对于30%

    实际上每个地方如果选了则代价就是i*a[i],贡献是a[i]。就可以直接跑01背包。

    对于100%

    考虑设f[i][j]表示只选择后头i--n个餐馆,吃了j个食物所需要的最小代价。转移方程很简单(f[i][j]=min(f[i+1][j],f[i+1][j-a[i]]+a[i]*i)),特别的,f[i][a[i]]可以从和2*i+i*a[i]取min。

    分析复杂度,因为从i带着j的食物回到0所需最小代价为i*j所以j只需枚举到x/i即可,复杂度为O(nlogm)。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e5+5;
    int n,k,a[N],f[2][N*10],l,r,ans;//f[i][j]表示在i-n这些餐馆中吃了j坨食物所花最小代价。 
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    signed main()
    {
        //freopen("w.in","r",stdin);
        //freopen("w.out","w",stdout);
        n=read();k=read();
        for(int i=1;i<=n;i++) a[i]=read();
        memset(f,0x3f3f3f3f,sizeof(f));
        for(int i=n;i>=1;i--)
        {
            
            for(int j=0;j<=k/i;j++)
            {
                f[i%2][j]=f[(i+1)%2][j];
                if(j>=a[i]) 
                    f[i%2][j]=min(f[(i+1)%2][j],f[(i+1)%2][j-a[i]]+i*a[i]);
                if(f[i%2][j]<=k) ans=max(ans,j);
            }
            f[i%2][a[i]]=min(f[i%2][a[i]],i+i+a[i]*i);
            if(i+i+a[i]*i<=k) ans=max(ans,a[i]);
        }
        cout<<ans;
    //    fclose(stdin);
    //    fclose(stdout); 
        return 0;
    }
    /*
    5 10
    1 1 1 1 1
    */
    View Code
  • 相关阅读:
    Upgrading to MySQL 5.7---focusing on temporal types
    mysqldump备份7
    mysqldump原理5
    mysqldump原理4
    mysqldump原理3
    mysqldump原理2
    mysqldump原理1
    MySQL复制中slave延迟监控
    赵浮云的blog 关注IT运维,开源硬件。
    爱维帮---LVS
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12215990.html
Copyright © 2020-2023  润新知