UVALive 6953 Digi Comp II(拓扑)

题意:

   m个开关,n个球。每个开关有两个状态,左或右,左则滚到左边,右则滚到右边。每滚一个球状态则反转一次。问最后每个开关的状态是怎样的。


解题:

  因为球数实在太多(10^18),一个一个模拟果断不行,而开关的最后状态只取决于滚过的球数和初始状态。所以计算出每个点球的流量并记录节点初始的状态即可。

注意:左右可以连同一个点!!!并且一开始不仅仅只有一为度数为零的点


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 500010
struct node
{
    ll l,r;
    ll num;
    ll in;
    bool status;
}id[maxn];
int main()
{
    long long n, m;
    while(~scanf("%lld%lld", &n, &m))
    {
        memset(id, 0, sizeof(id));
        char s[20];
        long long a, b;

        for(int i = 1; i <= m; i++)
        {
            scanf("%s%lld%lld", s,&a,&b);
            id[i].l = a;id[i].r = b;
            if(s[0] == 'L')
                id[i].status = 1;
            else
                id[i].status = 0;
            id[a].in++,id[b].in++;
        }
        id[1].num = n;
        queue<int>q;
        for(int i = 1; i <= m; i++)
        {
            if(id[i].in == 0)
                q.push(i);
        }
        while(!q.empty())
        {
            int tmp = q.front();
            q.pop();   //printf("---%d %d\n",tmp,id[tmp].num);
            long long  L = id[tmp].l, R = id[tmp].r;
            long long X = (id[tmp].num + 1)/2;
            long long Y = id[tmp].num - X;
            if(L || R)
            {
                 if(id[tmp].status)
                        id[L].num += X,id[R].num += Y;
                 else id[L].num += Y,id[R].num += X;
                 id[L].in--,id[R].in--;                 
                     if(L && id[L].in == 0)
                        q.push(L);
                     if(L != R &&R && id[R].in == 0)
                        q.push(R);
            }
        }
        //for(int i = 1; i <= m; i++)
            //printf("%d   %d\n",i,id[i].num);
        for(int i = 1; i <= m; i++)
        {
            if(id[i].num % 2) id[i].status = !id[i].status;
            if(id[i].status)
                printf("L");
            else printf("R");
        }
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值