2.7日学习总结

昨天考了试,现在来浅浅总结一下:

Problem Statement

You are given a simple undirected graph with �N vertices numbered 11 to �N and �M edges numbered 11 to �M. Edge �i connects vertex ��ui​ and vertex ��vi​.
Find the number of connected components in this graph.

Notes

simple undirected graph is a graph that is simple and has undirected edges.
A graph is simple if and only if it has no self-loop or multi-edge.

subgraph of a graph is a graph formed from some of the vertices and edges of that graph.
A graph is connected if and only if one can travel between every pair of vertices via edges.
connected component is a connected subgraph that is not part of any larger connected subgraph.

Constraints

  • 1≤�≤1001≤N≤100
  • 0≤�≤�(�−1)20≤M≤2N(N−1)​
  • 1≤��,��≤�1≤ui​,vi​≤N
  • The given graph is simple.
  • All values in the input are integers.

Input

The input is given from Standard Input in the following format:

�N �M
�1u1​ �1v1​
�2u2​ �2v2​
⋮⋮
��uM​ ��vM​

Output

Print the answer.

Sample 1

InputcopyOutputcopy
5 3
1 2
1 3
4 5
2

The given graph contains the following two connected components:

  • a subgraph formed from vertices 11, 22, 33, and edges 11, 22;
  • a subgraph formed from vertices 44, 55, and edge 33.

Sample 2

InputcopyOutputcopy
5 0
5

Sample 3

InputcopyOutputcopy
4 6
1 2
1 3
1 4
2 3
2 4
3 4

其实这个题之前考过,那时候没时间看,但是后来还是补过题的,但是这次考试我花了整整30多分钟才做出来!!!!!,原题啊啊啊,原因竟是少了一个初始化,所以还是要记录一下的:

#include<stdio.h>
int f[101]; int n,m;
void init()
{
    for(int i=1;i<=n;i++)
        f[i]=i;
}
int getf(int v)
{
    if(f[v]==v)
        return v;
    else
    {
        f[v]=getf(f[v]);
         return f[v];
}
    }

void merge(int v,int u)
{
    int t1=getf(u);
    int t2=getf(v);
    if(t1!=t2)
    {
        f[t2]=t1;

    }

}
int main()
{

    int g,h;
    scanf("%d %d",&n,&m);
  init();
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&g,&h);
        merge(g,h);
    }
    int ans=0;//我多花的二十分钟
    for(int i=1;i<=n;i++)
    {
        if(f[i]==i)ans++;
    }
    printf("%d",ans);
    return 0;

}

 事实告诉我们,必须要重视小细节啊啊!!血泪史!!

Define the score of some binary string �T as the absolute difference between the number of zeroes and ones in it. (for example, �=T= 010001 contains 44 zeroes and 22 ones, so the score of �T is ∣4−2∣=2∣4−2∣=2).

Define the creepiness of some binary string �S as the maximum score among all of its prefixes (for example, the creepiness of �=S= 01001 is equal to 22 because the score of the prefix �[1…4]S[1…4] is 22 and the rest of the prefixes have a score of 22 or less).

Given two integers �a and �b, construct a binary string consisting of �a zeroes and �b ones with the minimum possible creepiness.

Input

The first line contains a single integer �t (1≤�≤1000)(1≤t≤1000)  — the number of test cases. The description of the test cases follows.

The only line of each test case contains two integers �a and �b (1≤�,�≤1001≤a,b≤100)  — the numbers of zeroes and ones correspondingly.

Output

For each test case, print a binary string consisting of �a zeroes and �b ones with the minimum possible creepiness. If there are multiple answers, print any of them.

Sample 1

InputcopyOutputcopy
5
1 1
1 2
5 2
4 5
3 7
10
011
0011000
101010101
0001111111

Note

In the first test case, the score of �[1…1]S[1…1] is 11, and the score of �[1…2]S[1…2] is 00.

In the second test case, the minimum possible creepiness is 11 and one of the other answers is 101.

In the third test case, the minimum possible creepiness is 33 and one of the other answers is 0001100.

这个题目只能说刚开始只看案例去了,列了很多情况,然后一直过不了,钻研了许久,其实只要1010交替然后将多余的往后面放就行,这里带了绝对值,不管01在前面都没什么影响。还有一点是有时候看题也要有自己的思考,我看下面的注释的时候,它说还有另一种情况,我当时就以为就那几种情况,其实还有,它没说还有其他的情况,但也没说没有。QAQ....这里给两个ac代码,一个是01交替,另一个是10交替:

先看01交替

#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d %d",&a,&b);



            int t=(a>b)?b:a;

                for(int i=1;i<=t;i++)
                {
                    printf("1");
                 b--;


                 printf("0");
                 a--;

                }

               if(a==0)
               {
                   for(int i=1;i<=b;i++)
                printf("1");
               }

               if(b==0)
               {
                   for(int i=1;i<=a;i++)
               printf("0");
               }




         printf("\n");





    }
    return 0;
}

10交替:

#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d %d",&a,&b);



            int t=(a>b)?b:a;

                for(int i=1;i<=t;i++)
                {
                    printf("0");
                 a--;


                 printf("1");
                 b--;

                }

               if(a==0)
               {
                   for(int i=1;i<=b;i++)
                printf("1");
               }

               if(b==0)
               {
                   for(int i=1;i<=a;i++)
               printf("0");
               }




         printf("\n");





    }
    return 0;
}

小贴士:直接打印数字比打印变量里装的数字更快哦(本人想起来之前写的一道题就是这样,打印变量时间超限,使用技巧打印数字就不会)

所以,这里来验证一下,由于这里的数就两个,可能打印变量就不会慢的这么明显:

#include<stdio.h>
int main()
{
    int g=1,m=0;
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d %d",&a,&b);



            int t=(a>b)?b:a;

                for(int i=1;i<=t;i++)
                {
                    printf("%d",m);
                 a--;


                 printf("%d",g);
                 b--;

                }

               if(a==0)
               {
                   for(int i=1;i<=b;i++)
                printf("%d",g);
               }

               if(b==0)
               {
                   for(int i=1;i<=a;i++)
               printf("%d",m);
               }




         printf("\n");





    }
    return 0;
}

这也是通过了的,打印变量的现在来看下时间:

 看,时间还是有差距的,虽然是毫秒(上面是打印变量);

然后再看下一题:

Let's call a binary string �T of length �m indexed from 11 to �m paranoid if we can obtain a string of length 11 by performing the following two kinds of operations �−1m−1 times in any order :

  • Select any substring of �T that is equal to 01, and then replace it with 1.
  • Select any substring of �T that is equal to 10, and then replace it with 0.

    For example, if �=T= 001, we can select the substring [�2�3][T2​T3​] and perform the first operation. So we obtain �=T= 01.

You are given a binary string �S of length �n indexed from 11 to �n. Find the number of pairs of integers (�,�)(l,r) 1≤�≤�≤�1≤l≤r≤n such that �[�…�]S[l…r] (the substring of �S from �l to �r) is a paranoid string.

Input

The first line contains an integer �t (1≤�≤10001≤t≤1000) — the number of test cases. The description of test cases follows.

The first line of each test case contains a single integer �n (1≤�≤2⋅1051≤n≤2⋅105) — the size of �S.

The second line of each test case contains a binary string �S of �n characters �1�2…��S1​S2​…Sn​. (��=Si​= 0 or ��=Si​= 1 for each 1≤�≤�1≤i≤n)

It is guaranteed that the sum of �n over all test cases doesn't exceed 2⋅1052⋅105.

Output

For each test case, output the number of pairs of integers (�,�)(l,r) 1≤�≤�≤�1≤l≤r≤n such that �[�…�]S[l…r] (the substring of �S from �l to �r) is a paranoid string.

Sample 1

InputcopyOutputcopy
5
1
1
2
01
3
100
4
1001
5
11111
1
3
4
8
5

Note

In the first sample, �S already has length 11 and doesn't need any operations.

In the second sample, all substrings of �S are paranoid. For the entire string, it's enough to perform the first operation.

In the third sample, all substrings of �S are paranoid except [�2�3][S2​S3​], because we can't perform any operations on it, and [�1�2�3][S1​S2​S3​] (the entire string).

这个题目想了好久,模拟了好久,都没写出来,看懂这个题目也费了我不少时间,还是学长教的,现在我来深度剖析一下这个原理:(在此之前,先看清题,01可以变为1,10变为0别反了,不然会很惨),当然,题目意思也要理解,这里是求一个串里面的可以通过01和10操作能变成长度为一的串串的个数。先看这个数组,很容易可以想到对于1前面的0不论多少个连续的零都可以最后将这一堆变成1:比如001可以变成1,000000001还是可以变成1,而对于0前面的1,不论多少个连续的1都会将这一坨变成0:比如1111111110可以变成0,明白了这个,我们就很好解释了,先上代码:

#include<stdio.h>
char a[200001];//刚开始狂输整数,一直出不来,才发现连在一起的要用字符TAT
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        long long ans=1;//别忘了每次用前初始化
        scanf("%d",&n);//一定要记得先输入再使用,我之前经常先用再输入,时常出不来
        scanf("%s",a+1);//如果没加一就是从a[0]开始
        for(int i=1;i<n;i++)
        {
            if(a[i]!=a[i+1])ans+=i+1;
            else ans+=1;
        }
        printf("%lld\n",ans);

    }


    return 0;//记得放在循环外
}

本来学长教了一个在这个基础上改进的代码,但是之前还是有一点没明白,但是看完这位同学的博客,我直呼666,出了这段较为直观的代码,感谢这位同学!!!这是她的博客:

(16条消息) 复习题&&第五次测试E_m0_图灵灵的博客-CSDN博客

当然,其实这个代码打完我还是有点疑问,所以这时候画图就成了很好的工具帮助理解啦:

 

 

 

最后再来点心灵鸡汤吧:很喜欢《瓦尔登湖》里面的这句话:倘若一个人信心满怀的朝他的梦想的方向前进,努力过上他想象的那种生活,那他都会在平常的时光里获得意外的成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级喜欢沾着麻子吃的饺子

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值