• Papa的坦克(原BZOJ 1603 打谷机)


    题目描述
    时间限制 1s 空间限制 128MB Papa有一辆很厉害的坦克,它需要齿轮来带动。发动机驱动轮1总是顺时针旋转的,用来带动转轮2,转轮2来带动转轮3,等等。

    一共有n(2<=n<=1000)个齿轮(和n-1条链条)。齿轮有两种连接方式,第一种方式使得两个轮子旋转的方向相同,第二种则相反。 给出一串带子的信息: Si—驱动轮 Di—被动轮 *Ci—连接的类型(0=直接连接,1=交叉连接) 不幸的是,列出的信息是随机的。 作为样例, n=4,转轮1是驱动轮,可以得知最后转轮4是逆时针旋转。

    输入格式
    第一行:一个数n 第二行到第n行:每一行有三个被空格隔开的数:Si,Di,Ci

    输出格式
    第一行:一个单独的数,表示第n个转轮的方向,0表示顺时针,1表示逆时针


    样例输入
    4
    2 3 0
    3 4 1
    1 2 0

    样例输出

      1


     嗯...这是我们学校测试的第一题,虽然不难,但还是考验图论的基本功的,有意想做了测评的到该站 http://www.nyzoj.com:5283/problem/10037

    dfs解法:

    因为建边时驱动轮在前,被动轮在后,所以只用建单向边就可以了

    然后dfs从1开始遍历到n,我们用一个f[]数组来存状态,因为0表示顺时针,所以起始的f[1]只要定义成全局变量就不用初始化了

    在dfs过程中要用到“^” 运算符,意思是“异或” ,如果a=b  then  a^b=0  else  return |a-b|

    就很好的运用到了本题,如果下一个轮的连接方式与上一个轮的转向相同则为顺,即是 0 ,不同则为逆,则是 1

    代码如下:

    #include<stdio.h>
    
    struct Edge{
        int to,next,val;
    }edge[1001];
    int n,cnt,first[1001],f[1001];
    
    void add(int from,int to,int val)
    {
        edge[++cnt].to=to;
        edge[cnt].val=val;
        edge[cnt].next=first[from];
        first[from]=cnt;
    }
    
    void dfs(int x,int from)
    {
        for(int i=first[x];i;i=edge[i].next)
        {
            f[edge[i].to]=f[x]^edge[i].val;
            dfs(edge[i].to,x);
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        int from,to,val;
        while(scanf("%d%d%d",&from,&to,&val)!=EOF){
            add(from,to,val);
        }
        dfs(1,0);
        printf("%d",f[n]);
        return 0;
    }

    拆点并查集解法:

    #include<cstdio>
    #include<cstring>
    int ufs[5000];
    
    int Find(int x)
    {
        return ufs[x] ==x?x:ufs[x]= Find(ufs[x]);
    }
    
    int main()
    {
        int n, i, t1, t2, x, y, t;
        scanf("%d", &n);
        {
            memset(ufs, 0, sizeof(ufs));
            for(i=1; i<=n*2+1 ;i++)
                ufs[i]=i;
            for(i=1;i<=n-1;i++)
            {
                scanf("%d%d%d", &x, &y, &t);
                if(t==0)
                {
                    t1 = Find(x);
                    t2 = Find(y);  
                    ufs[t1] = t2;
            
                    t1 = Find(x+n);
                    t2 = Find(y+n);  
                    ufs[t1] = t2;
                }
                else
                {
                    t1 = Find(x);
                    t2 = Find(y+n);  
                    ufs[t1] = t2;
                    
                    t1 = Find(x+n);
                    t2 = Find(y);
                    ufs[t1] = t2;
                }
            }
            if(Find(1)==Find(n))
                printf("0
    ");
            else
                printf("1
    ");
        }
        return 0;
    }
    从0到1很难,但从1到100很容易
  • 相关阅读:
    二、JAVA通过JDBC连接mysql数据库(操作)
    一、JAVA通过JDBC连接mysql数据库(连接)
    while loading persisted sessions [java.io.EOFException]的三种解决办法!
    8大排序算法的java实现--做个人收藏
    数据库索引实现原理—B_TREE
    数据库查询优化方法
    webservice原理及基于cxf开发的基本流程
    Java多线程之Thread、Runnable、Callable及线程池
    随机数问题--已知有个Random7()的函数,返回1到7随机自然数,让利用这个Random7()构造Random10()随机1~10.
    深入Java—String源代码
  • 原文地址:https://www.cnblogs.com/qseer/p/9386415.html
Copyright © 2020-2023  润新知