hdu 3394 Railway(Tarjan,点双连通分量)

看题意请移步:http://blog.csdn.net/kopyh/article/details/48345773
然后就上板子。
tle了一个多小时,找很多博客的代码对比,调试啊,最后发现是数组开小了,即使开小了,也比题目给的数据范围还是要大的。内存开销为啥是tle?

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 20010;
const int MAXM = 200100;
struct Edge
{
    int to,next;
};
Edge edge[MAXM];
int head[MAXN];
int Low[MAXN],Dfn[MAXN],Stack[MAXN];
int tmp[MAXN];
int Index,top,Bridge,cc,res,tot;
bool ok[MAXN];

void init()
{
    memset(Dfn,0,sizeof(Dfn));
    memset(Low,0,sizeof(Low));
    memset(head,-1,sizeof(head));
    Index = top = tot = Bridge = res = 0;
}

void addedge(int u, int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void calc()
{
    int sum = 0,u,v;
    for(int i = 0; i < cc; ++i)
    {
        u = tmp[i];
        for(int j = head[u]; ~j; j = edge[j].next)
        {
            v = edge[j].to;
            if(ok[v]) sum++;
        }
    }
    sum /= 2;//因为是无向图,所以要除以2,算出总边数
    //如果边数大于点数,肯定有环
    if(sum > cc)
        res += sum;
}

void Tarjan(int u, int fa)
{
    Low[u] = Dfn[u] = ++Index;
    Stack[top++] = u;
    for(int i = head[u]; ~i;  i = edge[i].next)
    {
        int v = edge[i].to;
        if(!Dfn[v])
        {
            Tarjan(v,u);
            Low[u] = min(Low[u],Low[v]);
            if(Low[v] > Dfn[u]) ++Bridge;
            if(Low[v] >= Dfn[u])
            {
                int vn;
                cc = 0;//cc用于计数当前点连通分量中的点的个数
                memset(ok,false,sizeof(ok));
                do
                {
                    vn = Stack[--top];
                    ok[vn] = true;//ok用于标记当前点连通分量中的点
                    tmp[cc++] = vn;
                }while(vn != v);
                tmp[cc++] = u;
                ok[u] = true;
                calc();
            }
        }
        else if(v != fa)
            Low[u] = min(Low[u],Dfn[v]);
    }
}

void solve(int n)
{
    for(int i = 1; i <= n; ++i)
        if(!Dfn[i])
            Tarjan(i,-1);
}
int main()
{
    int n,m,u,v;
    while(scanf("%d %d",&n,&m) && n+m)
    {
        init();
        for(int i = 0; i < m; ++i)
        {
            scanf("%d %d",&u,&v);
            addedge(u+1,v+1);
            addedge(v+1,u+1);
        }
        solve(n);
        printf("%d %d\n",Bridge,res);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值