• P3469 [POI2008]BLO-Blockade tarjan


    好久没发博客了啊!自我反省1s。。。今天再捡起来。

    这个题是一道有一点特殊的tarjan,用tarjan维护子树大小,然后判断是否有边多次连接,(就是非树边),然后就进行乘法计算就行了。

    具体在代码里讲:

    题干:

    在Byteotia有n个城镇。 一些城镇之间由无向边连接。 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些)。每两个城镇之间至多只有一条直接连接的道路。人们可以从任意一个城镇直接或间接到达另一个城镇。 每个城镇都有一个公民,他们被孤独所困扰。事实证明,每个公民都想拜访其他所有公民一次(在主人所在的城镇)。所以,一共会有n*(n-1)次拜访。
    
    不幸的是,一个程序员总罢工正在进行中,那些程序员迫切要求购买某个软件。
    
    作为抗议行动,程序员们计划封锁一些城镇,阻止人们进入,离开或者路过那里。
    
    正如我们所说,他们正在讨论选择哪些城镇会导致最严重的后果。
    
    编写一个程序:
    
    读入Byteotia的道路系统,对于每个被决定的城镇,如果它被封锁,有多少访问不会发生,输出结果。
    输入输出格式
    
    第一行读入n,m,分别是城镇数目和道路数目
    
    城镇编号1~n
    
    接下来m行每行两个数字a,b,表示a和b之间有有一条无向边
    
    输出n行,每行一个数字,为第i个城镇被锁时不能发生的访问的数量。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;i++)
    #define lv(i,a,n) for(register int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    struct node
    {
        int l,r,nxt;
    }a[1000005];
    int len = 0,lst[500005],n,m;
    int dfn[500005],low[500004],cnt = 0,siz[500005];
    ll ans[500005];
    void add(int x,int y)
    {
        a[++len].l = x;
        a[len].r = y;
        a[len].nxt = lst[x];
        lst[x] = len;
    }
    void tarjan(int x)
    {
        dfn[x] = low[x] = ++cnt;
        siz[x] = 1;
        int z = 0;
        for(int k = lst[x];k;k = a[k].nxt)
        {
            int y = a[k].r;
            if(!dfn[y])
            {
                tarjan(y);
                low[x] = min(low[x],low[y]);
                siz[x] += siz[y];
                if(dfn[x] <= low[y]) //是否有非树边连接上下两端
                {
                    ans[x] += (ll)z * siz[y];
                    z += siz[y];
                }
            }
            else
            low[x] = min(low[x],dfn[y]);
        }
        ans[x] += (ll)z * (n - z - 1);//自己那也去不了
    }
    int main()
    {
        read(n);read(m);
        duke(i,1,m)
        {
            int x,y;
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        /*duke(i,1,n)
        {
            if(!dfn[i])
            {
                tarjan(i);
            }
        }*/
        tarjan(1);//一定是连通的,所以不用循环
        duke(i,1,n)
        {
            printf("%lld
    ",(ans[i] + n - 1) << 1);
        }
        return 0;
    }
  • 相关阅读:
    从FxCop归纳出来的一些规范建议
    UML用例建模的慨念和应用
    Android 截屏脚本
    悲剧的账户绑定与通讯录丢失实录
    文件分享功能实现
    Java字符串与整数之间的互相转换
    关于大的Bitmap保存问题
    将程序关联成Android系统默认打开程序
    关于Android应用多语言支持实现
    关于通过getWidth与getHeight获取bitmap​的尺寸与其实际尺寸不符合问题
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9866364.html
Copyright © 2020-2023  润新知