hdu 3749 Financial Crisis(Tarjan,点双连通分量)

来源:互联网 发布:淘宝500字差评范文 编辑:程序博客网 时间:2024/05/03 21:49

给你一个无向图,并且保证输入无重边,无自环,然后给你Q个询问,询问u,v之间有几条路径(除了首位之外,其余的路径节点不重复)。没有路径输出 zero,有一条路径输出one,两条或以上输出two or more.
思路:点双连通分量。先用并查集判断两点是否能连通,不能连通则输出zero,能连通的话,则判断是否在同一个双连通分量,有一种双连通分量内只有两个点,有一条边。这种情况输出one,双连通分量内点数 > 2 输出two or more,如果两个点连通但不在同一个连通分量内,输出one。
因为割点可以属于多个连通分量,所以用vector记录每个点属于哪个连通分量.
数组开大点,不然tle。

#include <bits/stdc++.h>using namespace std;const int MAXN = 10555;const int MAXM = 21111;struct Edge{    int to,next;};Edge edge[MAXM];int head[MAXN],Stack[MAXN],Low[MAXN],Dfn[MAXN],f[MAXN],Count[MAXN];vector<int> Belong[MAXN];int tot,top,Index,block,cc;void init(){    memset(head,-1,sizeof(head));    memset(f,-1,sizeof(f));    tot = 0;}void addedge(int u, int v){    edge[tot].to = v;    edge[tot].next = head[u];    head[u] = tot++;}int getf(int x){    if(f[x] == -1)        return x;    return f[x]=getf(f[x]);}void mmerge(int u, int v){    u = getf(u);    v = getf(v);    if(u != v)        f[v] = u;}void Tarjan(int u, int fa){    Low[u] = Dfn[u] = ++Index;    Stack[top++] = u;    for(int i = head[u]; i != -1; 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])            {                block++;                cc = 0;                int vn;                do                {                    vn = Stack[--top];                    ++cc;                    Belong[vn].push_back(block);                }while(vn != v);                Belong[u].push_back(block);                Count[block] = cc+1;            }        }        else if(v != fa)            Low[u] = min(Low[u],Dfn[v]);    }}void solve(int n){    memset(Low,0,sizeof(Low));    memset(Dfn,0,sizeof(Dfn));    memset(Count,0,sizeof(Count));    Index = top = block = 0;    for(int i = 1; i <= n; ++i)        Belong[i].clear();    for(int i = 1; i <= n; ++i)        if(!Dfn[i])            Tarjan(i,-1);}int main(){    int n,m,q,u,v,time = 0;;    while(scanf("%d %d %d",&n,&m,&q) && n+m+q)    {        init();        for(int i = 0; i < m; ++i)        {            scanf("%d %d",&u,&v);            u++,v++;            mmerge(u,v);            addedge(u,v);            addedge(v,u);        }        solve(n);        printf("Case %d:\n",++time);        while(q--)        {            scanf("%d %d",&u,&v);            u++,v++;            if(getf(u) != getf(v))            {                printf("zero\n");                continue;            }            bool flag = false;            int res = -1;            for(int i = 0; i < Belong[u].size(); ++i)            {                for(int j = 0; j < Belong[v].size(); ++j)                {                    if(Belong[u][i] == Belong[v][j])                    {                        flag = true;                        res = Belong[u][i];                        break;                    }                }                if(flag) break;            }            if(res != -1 && Count[res] > 2)                printf("two or more\n");            else                printf("one\n");        }    }    return 0;}