SDUT 2170 The Largest SCC bfs+tarjan

题意:

给你一个n个点,m条有向边的图,然后给你k个操作,每次把第i个边改变成无向边。然后求该图的强连通块里面点数最多的值

思路:

首先bfs求出每个点可达的边,然后tarjan求出强连通块。每次改变边时,如果这条边的两个端点在同一连通块(u,v),直接输出最多。如果不在同一连通块,首先加上这两个连通块的个数组成新的连通块,然后枚举i u->i ,i>v满足,然后i不属于u或者v的连通块,然后加上该连通块数量即可。

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val)    memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define ll __int64

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout);





#define M 20010

#define N 1010

using namespace std;

const int mod = 1000000007;



bool isok[N][N];

struct node

{

    int u,v;

}nd[M];



struct side

{

    int v;

    int next;

}g[M];



int dfn[N],low[N];

int belong[N],stk[N];

bool ins[N];

int cnt,top,idx;



int head[N],ct;



bool vt[N];

int num[N];

int n,m,k;

int ans;



void init()

{

    for (int i = 0; i <= n; ++i)

    {

        dfn[i] = low[i] = belong[i] = -1;

        ins[i] = false;

        head[i] = -1;

        num[i] = 0;

    }

    cnt = idx = ct = top = 0;

}

void add(int u,int v)

{

    g[ct].v = v;

    g[ct].next = head[u];

    head[u] = ct++;

}

void bfs(int s)

{

    queue<int> Q;

    vt[s] = true;

    Q.push(s);

    while (!Q.empty())

    {

        int u = Q.front(); Q.pop();

        for (int i = head[u]; i != -1; i = g[i].next)

        {

            int v = g[i].v;

            if (!vt[v])

            {

                vt[v] = true;

                isok[s][v] = true;

                Q.push(v);

            }

        }

    }

}

void tarjan(int u)

{

    int i,v;

    low[u] = dfn[u] = ++idx;

    stk[++top] = u; ins[u] = true;

    for (i = head[u]; i != -1; i = g[i].next)

    {

        v = g[i].v;

        if (dfn[v] == -1)

        {

            tarjan(v);

            low[u] = min(low[u],low[v]);

        }

        else if (ins[v])

        {

            low[u] = min(low[u],dfn[v]);

        }

    }

    if (dfn[u] == low[u])

    {

        cnt++;

        do{

            v = stk[top--];

            ins[v] = false;

            belong[v] = cnt;

            num[cnt]++;

        }while (v != u);

        ans = max(ans,num[cnt]);

    }

}

int main()

{

//    Read();

    int T,i,j;

    scanf("%d",&T);

    while (T--)

    {

        scanf("%d%d%d",&n,&m,&k);

        init();

        for (i = 1; i <= m; ++i)

        {

            scanf("%d%d",&nd[i].u,&nd[i].v);

            add(nd[i].u,nd[i].v);

        }

        CL(isok,false);//标记两点是否可达

        

        //找出每个每个点可达的点

        for (i = 1; i <= n; ++i)

        {

            for (j = 1; j <= n; ++j) vt[j] = false;

            bfs(i);

        }

        ans = 0;

        for (i = 1; i <= n; ++i)

        {

            if (dfn[i] == -1)

            {

                tarjan(i);

            }

        }

        int x;

        while (k--)

        {

            scanf("%d",&x);

            int u = nd[x].u;

            int v = nd[x].v;

            int sum = ans;

            if (belong[u] == belong[v])

            {

                printf("%d\n",sum);

            }

            else

            {

                int tmp = num[belong[u]] + num[belong[v]];

                for (j = 1; j <= n; ++j) vt[j] = false;//这里表示该连通块是否已经加入

                for (i = 1; i <= n; ++i)

                {

                    if (belong[i] == belong[u] || belong[i] == belong[v]) continue;



                    if (isok[u][i] && isok[i][v] && !vt[belong[i]])

                    {

                        vt[belong[i]] = true;

                        tmp += num[belong[i]];

                    }

                }

                sum = max(sum,tmp);

                printf("%d\n",sum);

            }

        }

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(tar)