zoukankan      html  css  js  c++  java
  • Codeforces Round #311 (Div. 2)

    D

    分4种情况讨论

    1 不需要加边 , 就是说原本就有一个奇数环,我们只要跑一次二分图就好了

    2 加一条边 , 也就是说存在大于等于3个点的联通块 我们对于这个联通块也跑一遍二分图, 可以知道图中所有的 同颜色染色中的点任意相连,都是一个奇数环,那么对于每个联通分量都有相应的数可以计算

    3 加两条边,也就是说没有大于两个点的联通块存在,并且有两个点的联通块存在,答案也是可以计算出来的 e*(n-2)

    4 加三条边 那么就可以知道每个联通块只有一个点,答案是 n*(n-1)*(n-2)/6;

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <cstdio>
    #include <vector>
    using namespace std;
    const int maxn=100005;
    typedef long long LL;
    int fa[maxn],Enum[maxn];
    pair<int,int>e[maxn];
    int fin(int a)
    {
         return fa[a]=(a==fa[a])?a:fin( fa[a] );
    }
    bool solve1(LL n,int m)
    {
        for(int i=0; i<m; i++)
            {
                 int a=e[i].first,b=e[i].second;
                 a=fin(a); b=fin(b);
                 if(a==b)continue;
                 Enum[a]+=Enum[b];
                 fa[b]=a;
            }
        LL num1=0,num2=0;
        for(int i=1; i<=n; i++)
            {
                if(fa[i]!=i)continue;
                if(Enum[i]>2)return false;
                if(Enum[i]==1)num1++;
                else num2++;
            }
         if(num2==0){
            LL d=n*(n-1)*(n-2)/6;
            printf("3 %I64d
    ",d);
         }else{
            LL d=num2*(n-2);
            printf("2 %I64d
    ",d);
         }
         return true;
    }
    int H[maxn],nx[maxn*2],to[maxn*2],numofedg;
    void add(int a, int b){
        numofedg++; to[numofedg]=b; nx[numofedg]=H[a]; H[a]=numofedg;
        numofedg++; to[numofedg]=a; nx[numofedg]=H[b]; H[b]=numofedg;
    }
    int color[maxn],num1,num2;
    bool bipartite(int u)
    {
        if(color[u]==1)num1++;
        else num2++;
        for(int i=H[u]; i; i=nx[i])
        {
              int v=to[i];
              if(color[u]==color[v])return false;
              if(color[v]==0){
                color[v]=3-color[u];
                if(bipartite(v)==false)return false;
              }
        }
        return true;
    }
    void solve2(LL n, int m)
    {
         for(int i=0; i<m; i++){
            add(e[i].first,e[i].second);
         }
         LL ans=0;
         memset(color,0,sizeof(color));
         for(int i=1; i<=n; i++)
            {
                 if(color[i]==0){
                    color[i]=1;
                    num1=num2=0;
                    if(bipartite(i)==false){
                        printf("0 1
    ");return ;
                    }else{
                       ans+= 1LL*num1*(num1-1)/2 +1LL*num2*(num2-1)/2;
                    }
                 }
            }
            printf("1 %I64d
    ",ans);
    }
    int main()
    {
       int n,m;
       scanf("%d%d",&n,&m);
       numofedg=0;
       for(int i=1; i<=n; i++){fa[i]=i,Enum[i]=1; H[i]=0; }
       for(int i=0; i<m; i++)
        {
          scanf("%d%d",&e[i].first,&e[i].second);
        }
        if(solve1(n,m)){return 0;}
        solve2(n,m);
        return 0;
    }
    View Code

    E

    题意 给了一个长度为5000的字符串  定义了奇回文 就是   i为奇数, 然后求出字符串的所有子串中 字典序第k大的那个并且是奇回文

    我们用dp[i][j] 计算出 以i为起点,j为终点的字符串是否为奇回文,这个很好转移

    然后我们将s[i----n]的字符串插入一棵字典树中 需要插入的字符有n个 ,然后对于每个dp[i][j] 是奇回文的串我们就在那个节点上加个1 然后就可以计算出最后的和值了

    因为他说的是所有组成 由ab组成 ok那就很好解了 

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <cstdio>
    #include <vector>
    using namespace std;
    const int maxn=5005;
    int dp[maxn][maxn],numofnode=0;
    char s[maxn];
    struct node
    {
       int ch[2];
       int S,Sloc,LS,RS;
       void init(int cSloc, int cLS, int cRS){
           Sloc=cSloc; LS=cLS; RS=cRS;
           S=Sloc+LS+RS;
       }
       void maintain()
       {
            S=Sloc+LS+RS;
       }
    }T[maxn*3000];
    void insert(int root,int len,int i,int j)
    {
        if(j==len){
                T[root].maintain();
                return;
        }
        int id=s[j]-'a';
        if(T[root].ch[id]==0){
            T[root].ch[id]=++numofnode;
            T[numofnode].ch[0]=T[numofnode].ch[1]=0;
            T[numofnode].init(0,0,0);
        }
        int u=T[root].ch[id];
        if(dp[i][j]) T[u].Sloc++;
        insert(u,len,i,j+1);
        T[root].LS=T[ T[root].ch[0] ].S;
        T[root].RS=T[ T[root].ch[1] ].S;
        T[root].maintain();
    }
    void find(int root, int k)
    {
         if(T[root].Sloc>=k)return ;
         k-=T[root].Sloc;
         if(T[root].LS>=k){
            printf("a");
            find(T[root].ch[0],k); return ;
         }
         k-=T[root].LS;
         printf("b");
         find(T[root].ch[1],k);
    }
    int main()
    {
        T[0].S=T[0].Sloc=0;
        T[1].init(0,0,0);
        T[1].ch[0]=T[1].ch[1]=0;
        numofnode=1;
        scanf("%s",s);
        int len=strlen(s);
         for(int i=1; i<=len; i++)
            for(int j=0; j<len; j++)
            {
                if(i+j>len)break;
                if( i == 1 )
                   dp[ j ][ i + j - 1 ] = true;
                else if( i == 2 || i == 3 || i == 4 )
                {
                    if(s[ j ] == s[ i + j - 1 ]){
                        dp[ j ][ i + j-  1 ]=true;
                    }else{
                        dp[ j ][ i + j - 1 ]=false;
                    }
                }else
                {
                    if(s[j]==s[i+j-1]){
                        dp[j][i+j-1]=dp[j+2][i+j-3];
                    }else{
                        dp[j][i+j-1]=false;
                    }
                }
    
            }
         for(int i=0; i<len; i++)
            {
                 insert(1,len,i,i);
            }
         int k;
         scanf("%d",&k);
         find(1,k);
        return 0;
    }
    View Code
  • 相关阅读:
    致此时的自己
    感悟
    Do what you love VS Love what you do
    感悟
    JavaScript中关于date对象的一些方法
    悟透JavaScript——学习心得
    JavaScript中关于string对象的一些方法
    JavaScript中的简单语句
    w3school CSS基础教程
    SMACSS——Scalable & Modular Architecture for CSS
  • 原文地址:https://www.cnblogs.com/Opaser/p/4811720.html
Copyright © 2011-2022 走看看