zoukankan      html  css  js  c++  java
  • Explosion at Cafebazaar

    Explosion at Cafebazaar

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    You are an engineer at Cafebazaar and your specialty is understanding networks and their behaviors. Your colleagues have designed a network of n switches with m directed links that connect pairs of these switches. Each switch has a buffer where it stores the data and two modes, called sending mode and receiving mode. In the sending mode, a switch sends the data stored in its buffer to each of its outgoing links simultaneously and at the end clears its buffer. In the receiving mode,a switch concatenates the data from all its incoming links and stores them in its buffer, so at the end, the length of the data stored in its buffer is equal to the sum of the lengths of all the data on the incoming links. 
    Assume that at time t = 0, all the switches are in sending mode and have an empty buffer except switch i which stores a 1-bit package of data in its buffer. Also, all the switches change their modes after each second, so at time t = 1 all the switches change to receiving mode, at time t = 2 they change to sending mode, and so on. Switch i is called explosive if the maximum length of data stored in the buffers of switches is not bounded as t goes to infinity. 
    Your task is to calculate the number of explosive switches in the network.

    输入

    There are multiple test cases in the input. The first line of each test case contains two space-separated integers n and m,where n indicates the number of switches and m indicates the number of directed links (1 ⩽ n, m ⩽ 50, 000). Each of the next m lines contains two space-separated integers u, v where (u, v) indicates a directed link from switch u to switch v (1 ⩽ u, v ⩽ n, u≠v). The input terminates with a line containing 0 0 which should not be processed.

    输出

    For each test case, output a single line containing the number of explosive switches.

    样例输入

    3 3
    1 2
    2 3
    3 1
    5 6
    1 2
    2 3
    3 1
    3 4
    4 5
    5 3
    4 5
    1 2
    2 3
    3 2
    3 2
    3 4
    0 0
    

    样例输出

    0
    5
    3
    

    来源/分类

    Tehran2016 


    题意:在n个点m条边的图中,每个点可以沿有向边发送数据,当然每个点也可以接收数据。每个点发送数据后,该点的数据就会清零,图中所有点发送和接收数据是同步的。(即它们一起发送数据,一起接收数据)。问在哪些点放上单位数据,可以使图中某些点的数据量达到无穷大。
    分析:要使单位数据最后变成无穷大数据,首先要有环。首先考虑单个环使数据爆炸的情况。环中必须存在某一点,它的入度大于等于2,这个环才能无限扩充数据。其次如果是简单的n个点n条边的环,它虽然不能使数据量增大,但是它可以源源不断的产生数据和保留数据,所以如果一个简单环连接着另一个环,那么这个简单环上的点也可以使数据爆炸。最后,所有连向数据爆炸环的点都可以使数据爆炸。
    做法:我的做法比较繁琐,我先求出了所有的环(强连通分量)并把环缩成点,再判一个环是否可以使数据爆炸,再判两个环是否可以使数据爆炸,最后反向跑dfs判连向爆炸环的点。
    #include<bits/stdc++.h>
    #define N 50050
    using namespace std;
     
    int dfn[N],low[N],vis[N],color[N],now_clock,now_color;
    int Stack[N],top;
    vector<int>edges[N];
    int explosive[N],du[N],sum_point[N],dfs2_vis[N],ans;
    vector<int>newedges[N];
    vector<int>edges2[N];
     
    void init(int n)
    {
        for(int i=0;i<=n;i++)edges[i].clear(),newedges[i].clear(),edges2[i].clear();
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        memset(explosive,0,sizeof(explosive));
        memset(du,0,sizeof(du));
        memset(sum_point,0,sizeof(sum_point));
        memset(dfs2_vis,0,sizeof(dfs2_vis));
        now_clock=1;
        top=0;
        now_color=1;
        ans=0;
     
    }
     
    void dfs(int x)
    {
        dfn[x]=low[x]=now_clock++;
        vis[x]=1;
        Stack[++top]=x;
         
        int Size=edges[x].size();
        for(int i=0;i<Size;i++)
        {
            int v=edges[x][i];
            if(!dfn[v])
            {
                dfs(v);
                low[x]=min(low[x],low[v]);
            }
            else
            if(vis[v])low[x]=min(low[x],dfn[v]);
        }
         
        if(dfn[x]==low[x])
        {
            while(Stack[top]!=x)
            {
                vis[Stack[top]]=0;
                color[Stack[top]]=now_color;
                top--;
            }
     
            vis[Stack[top]]=0;
            color[Stack[top]]=now_color++;
            top--;
        }
    }
     
    void dfs2(int x)
    {
        if(!dfs2_vis[x])
        {
            dfs2_vis[x]=1;
            ans+=sum_point[x];
        }
         
        int Size=newedges[x].size();
        for(int i=0;i<Size;i++)
        if(!dfs2_vis[newedges[x][i]])
        dfs2(newedges[x][i]);
     
    }
     
    int dfs3(int x)
    {
        if(sum_point[x]>=2)return 1;
         
        int Size=edges2[x].size();
        for(int i=0;i<Size;i++)
        if(dfs3(edges2[x][i]))return 1;
         
        return 0;
    }
     
     
    int main()
    {
     
        int n,m;
        while(scanf("%d %d",&n,&m)==2)
        {
            if(!n)return 0;
     
            init(n);
             
            while(m--)
            {
                int u,v;
                scanf("%d %d",&u,&v);
                edges[u].push_back(v);
            }
             
            for(int i=1;i<=n;i++)
            if(!dfn[i])dfs(i);
             
            for(int i=1;i<=n;i++)
            {
                int Size=edges[i].size();
                for(int j=0;j<Size;j++)
                {
                    int u=i,v=edges[i][j];
                    if(color[u]==color[v])
                    du[v]++;
                     
                }
            }
             
            for(int i=1;i<=n;i++)
            {
                sum_point[color[i]]++;
                if(du[i]>=2)explosive[color[i]]=1;
            }
        /*  for(int i=1;i<=n;i++)printf("%d ",color[i]);
            printf("
    ");
            for(int i=1;i<now_color;i++)printf("%d ",sum_point[i]);
            printf("
    ");
            for(int i=1;i<now_color;i++)printf("%d ",explosive[i]);
            printf("
    ");
            */
            for(int i=1;i<=n;i++)
            {
                int Size=edges[i].size();
                for(int j=0;j<Size;j++)
                {
                    int u=i,v=edges[i][j];
                    if(color[u]!=color[v])
                    {
                        newedges[color[v]].push_back(color[u]);
                        edges2[color[u]].push_back(color[v]);
                    }
                }
            }
             
            for(int i=1;i<now_color;i++)
            if(!explosive[i]&&sum_point[i]>=2)
            {
                int Size=edges2[i].size();
                for(int j=0;j<Size;j++)
                if(dfs3(edges2[i][j]))
                {
                    explosive[i]=1;
                    break;
                }
            }
             
            for(int i=1;i<now_color;i++)
            if(explosive[i])dfs2(i);
             
            printf("%d
    ",ans);
        }
         
        return 0;
    }
    View Code
  • 相关阅读:
    利用世界杯,读懂 Python 装饰器
    利用python开发app实战
    Python协程(真才实学,想学的进来)
    Python 中的 10 个常见安全漏洞,以及如何避免(上)
    Python学到什么程度才可以去找工作?掌握这4点足够了!
    Hadoop Yarn调度器的选择和使用
    CSS 预处理器 Stylus分享
    我想写小说了怎么回事...
    新随笔-- from笔试
    我是不是有点胖了
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9602331.html
Copyright © 2011-2022 走看看