SDUT 2170 The Largest SCC

来源:互联网 发布:notepad++ mac版中文 编辑:程序博客网 时间:2024/06/06 02:59

一句话题意:

​ 给出一个点数n1000 边数m20000 的有向图,一共Q20000次询问,询问相互独立,每次询问如果将第x(1xm)条边变为无向边时,图中最大的强连通分量所包含的点数为多少

首先做一次强连通分量的缩点肯定是不吃亏的(笑

如果第x条边的两个端点在同一个强连通分量内,其实这一次的更改边对缩点后的图是没有更改的,所以答案是原图中点最多的强连通分量

如果第x条边的两个端点不在同一个强连通分量内,不妨记该边的端点所在的强连通分量为startend,到那么这一次更改边会影响到的点其实就是从start出发到end中间所有能经过的点,也就是说,这些点在改边之后会被缩到一个联通分量内,那么只要统计出来就好了

具体的代码实现的,我们可以先预处理一个visx,y这样二维的bool矩阵,表示出来从x出发是否能到达y,这部分我们能通过ndfsbfs解决,然后每一次询问可以O(n)地回答,总的时间复杂度是O(n+n2+n×Q)


我是代码的分割线


#include<bits/stdc++.h>using namespace std;const int maxn = 1123;int dfn[maxn],low[maxn],_cnt;int bel[maxn];vector<int>edge[maxn];vector<int>scc[maxn];stack<int> S;void init(int n){    for(int i=0;i<n;i++){        edge[i].clear();    }    while(S.empty()==false)        S.pop();    memset(dfn,-1,sizeof(dfn));    memset(low,-1,sizeof(low));    memset(bel,-1,sizeof(bel));    _cnt = 1;}void dfs(int st){    S.push(st);    dfn[st] = low[st] = _cnt++;    for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){        int x = *it;        if(dfn[x] == -1){            dfs(x);            low[st] = min(low[st],low[x]);        }        else if(bel[x] == -1){            low[st] = min(low[st],dfn[x]);        }    }    if(low[st] == dfn[st]){        while(S.top()!=st){            bel[S.top()] = st;            S.pop();        }        bel[st] = st;        S.pop();    }}const int maxm = 21234;int from[maxm],to[maxm];int cnt[maxn];bool viser[maxn][maxn];void dffs(int st,bool *s){    s[st] = true;    for(vector<int>::iterator it = scc[st].begin();it!=scc[st].end();it++){        if(s[*it] == false){            dffs(*it,s);        }    }}void getvis(int n){    for(int i=1;i<=n;i++){        scc[i].clear();    }    for(int st = 1;st <= n;st++){        for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){            int f = bel[st];            int t = bel[*it];            if(f != t){                scc[f].push_back(t);            }        }    }    memset(viser,0,sizeof(viser));    for(int i=1;i<=n;i++){        if(bel[i] == i){            dffs(i,viser[i]);        }    }}int main(){    int T;    scanf("%d",&T);    int n ,m;    int q;    while(T-- && ~scanf("%d %d %d",&n,&m,&q)){        init(n);        for(int i=1;i<=m;i++){            scanf("%d %d",&from[i],&to[i]);            edge[from[i]].push_back(to[i]);        }        for(int i=1;i<=n;i++){            if(bel[i] == -1){                dfs(i);            }        }        memset(cnt,0,sizeof(cnt));        for(int i=1;i<=n;i++){            cnt[bel[i]]++;        }        getvis(n);        int x;        int maxer = *max_element(cnt+1,cnt+1+n);        while(q--){            scanf("%d",&x);            int f = bel[from[x]],t = bel[to[x]];            if(f == t){                printf("%d\n",maxer);            }            else{                int ans = 0;                for(int i=1;i<=n;i++){                    if(viser[f][i] && viser[i][t]){                        ans += cnt[i];                    }                }                printf("%d\n",max(maxer,ans));            }        }    }    return 0;}
0 0
原创粉丝点击