[UPC | 山东省赛] The Largest SCC | Tarjan强连通分量瞎搞 + 状态还原

简介: 题目描述Consider a directed graph with N (1 <= N <= 1000) vertices and M (0 <=M <= 20000) edges. The edges are numbered from 1 to M and the vertices are numbered from 1 to N. Now I will make ONE edge bidirectional, and you are to tell me the number of vertices of the largest strong connected components

题目描述


Consider a directed graph with N (1 <= N <= 1000) vertices and M (0 <=M <= 20000) edges. The edges are numbered from 1 to M and the vertices are numbered from 1 to N. Now I will make ONE edge bidirectional, and you are to tell me the number of vertices of the largest strong connected components in the new graph.The largest strong connected components is the strong connected components which has the most vertices. After the operation, I will change the edge back. There will be up to Q (1 <= Q <= 20000) such queries.


输入


At the firest of the input comes an integer t, indicates the testcases to follow.

The first line of each case contains three numbers N, M and Q. Then there will be M lines, each of them contains two numbers a,b (a! = b; 1 <= a; b <= N) means there is a directed edge between a and b. The last of each case contains Q lines, each of them contains one integer q, means the edge numbered q will be change to bidirectional. There will not be duplicated edges.


输出


For every query, output one line contains only one integer number, which is the number of vertices of the biggest strong connected components.


样例输入


1
5 4 2
1 2
2 3
1 3
4 1
1
3


样例输出


2
3


题意:


给出n 个点m 条边的图,边为有向边,q 此查询,如果每次将第k 条边变为双向边,问改变这一条边为双向边之后,图中的最大的强连通分量里面包含多少个点


思路1(wa):

首先求出SCC,将在同一个强连通分量里面的点用并查集维护在一起(此时顺便找出一个最大值),然后再加边[变为双向边其实就是加了一条从原来的终点向之前的起点的一条边]的时候,查看边的两个端点是不是在同一个强连通分量中,如果在同一个强连通分量中,就直接输出原来的最大值,如果说不是在同一个强连通分量中,就将两个强连通分量的大小与之前的最大值求一个最大进行输出,

这样是不对的,因为改变一条边之后,可能影响的不是两个端点所在的连通块,所以说这里不能够用这种方法来处理

应该是:

思路2(ac):

因为点的个数只有1000 ,所以我们直接每次加入一条新的边之后,重新进行Tarjan

比如说:第k条边是u->v 的,那么说我们应该加入一从v->u的边,这样一来,然后我们从u点开始重新进行Tarjan,因为在原始的图中,是u->v的,这样一来我们只需要记录影响的大小和原先最大值的大小取一个最大值即可

在进行Tarjan的时候,如果是一开始的预处理,是可以加入新的强连通分量的,但是在处理q此询问的时候,不可以有新的强连通分量产生,因为不能对原图进行修改,(每次询问都是单独的),而对于新加入的边,也要在下一次操作之前去掉,但是强连通分量的大小是可以改变的,每次找到最大的size


Code:


int n, m, q;
struct node {
  int to, nex;
} e[maxn << 2];
int cnt, head[maxn], dfc;
int dfn[maxn], low[maxn], pos[maxn];
int num[maxn], vis[maxn];
int cntSCC, ans;
void init() {
  cnt = dfc = cntSCC = 0;
  for(int i = 1; i <= n; i++) {
    head[i] = -1;
    pos[i] = vis[i] = 0;
  }
}
void add(int u, int v) {
  e[cnt].to = v;
  e[cnt].nex = head[u];
  head[u] = cnt ++;
}
stack<int> stk;
int mx,premx;
void Tarjan(int x) {
  int u = x;
  dfn[u] = low[u] = ++ dfc;
  vis[u] = 1;
  stk.push(u);
  for(int i=head[u]; ~i; i=e[i].nex) {
    int v = e[i].to;
    if(!dfn[v]) {
      Tarjan(v);
      low[u] = min(low[u],low[v]);
    } else if(vis[v]) {
      low[u] = min(low[u],dfn[v]);
    }
  }
  int tp;
  if(low[u] == dfn[u]) {
    ++ cntSCC;
    do{
      tp = stk.top();
      stk.pop();
      vis[tp] = 0;
      if(vis[0]) pos[tp] = cntSCC;
      num[cntSCC] ++;
      mx = max(mx,num[cntSCC]);
    }while(tp != u);
  }
}
typedef pair<int,int> PII;
vector<PII> save;
void ClearStack(){
  while(stk.size()) stk.pop();
}
int main() {
  int _ = read;
  while(_ --) {
    n = read,m = read,q = read;
    init();
    save.clear();
    memset(dfn,0,sizeof dfn);
    memset(low,0,sizeof low);
    memset(vis,0,sizeof vis);
    memset(num,0,sizeof num);
    vis[0] = 1;
    for(int i = 1; i <= m; i++) {
      int u = read, v = read;
      add(u, v);
      save.push_back({u,v});
    }
    ClearStack();
    mx = 0,premx = 0;
    for(int i=1; i<=n; i++) {
      if(!dfn[i]) Tarjan(i);
    }
    premx = mx;
//    cout << mx << endl;
//    cout << premx << endl;
    vis[0] = 0;
    while(q --) {
      int id = read - 1;
      PII eg = save[id];
      int u = eg.first,v = eg.second;
//      cout << u <<"  ->  " << v<< endl;
      if(pos[u] == pos[v]) {
        printf("%d\n",mx);
        continue;
      }
      add(v,u);
      memset(dfn,0,sizeof dfn);
//      memset(low,0,sizeof low);
      dfc = 0;
      ClearStack();
      Tarjan(u);
      printf("%d\n",mx);
      mx = premx;
      head[v] = e[--cnt].nex;
    }
  }
  return 0;
}




目录
相关文章
|
12月前
|
人工智能 算法 BI
LeetCode 周赛 341 场,模拟 / 树上差分 / Tarjan 离线 LCA / DFS
上周末有单双周赛,双周赛我们讲过了,单周赛那天早上有事没参加,后面做了虚拟竞赛,然后整个人就不好了。前 3 题非常简单,但第 4 题有点东西啊,差点就放弃了。最后,被折磨了一个下午和一个大夜总算把第 4 题做出来了,除了新学的 Tarjon 离线算法,这道题还涉及到树上差分、前缀和、DFS、图论等基础知识,几度被折磨得想要放弃。这种感觉,似乎和当年在 LeetCode 上做前 10 题的时候差不多哈哈。
64 0
|
人工智能 Python
2019CCPC厦门站 A. Zayin and Bus(bfs 贪心 排序)
2019CCPC厦门站 A. Zayin and Bus(bfs 贪心 排序)
62 0
|
人工智能 vr&ar
SPOJ - COT Count on a tree(主席树 LCA)
SPOJ - COT Count on a tree(主席树 LCA)
70 0
|
存储
UPC组队第三场——K: A Famous Grid (BFS+细节)
UPC组队第三场——K: A Famous Grid (BFS+细节)
61 0
UPC组队第三场——K: A Famous Grid (BFS+细节)
2015长春网络赛 —— B. Ponds (拓扑排序删点+DFS)
2015长春网络赛 —— B. Ponds (拓扑排序删点+DFS)
65 0
UPC组队赛第三场——G: The Famous ICPC Team Again (主席树)
UPC组队赛第三场——G: The Famous ICPC Team Again (主席树)
74 0
|
人工智能
[CCPC] 2017秦皇岛H Prime Set | 二分图最大匹配 [据说是个金牌题]
题意: 给出n个数,如果两数之和a i + a j a_i+a_ja i ​ +a j ​ (i ≠ j i \neq ji  ​ =j)为素数,那么这两个数的下标组成的集合{ i , j } {\{i,j}\}{i,j} 问最多挑选k个这样的集合,集合最大的大小是多少 思路: 将给出的n个数进行暴力两两求和,看两数之和是否为素数,将能够构成素数的两个数的下标连一条边 开始将match数组标记为− 1 -1−1,如果能够构成素数,那么将这个数标记为0 00 然后进行二分图最大匹配,如果说匹配的个数 ≥ k \ge k≥k 那么答案就是k ∗ 2 k*2k∗2
106 0
[UVA1364 | POJ | NC]Knights of the Round Table | Tarjan 求点双 | 二分图 | 综合图论
我们可以很轻松地发现,被提出的都是在点双连通分量之外的,比如该图中的1 和 5 ,那么怎么判断哪些点不在环中呢? 此时我们还可以逆向思考,不 在 环 中 的 = = 总 的 − 在 环 中 的,所以说现在问题就转换成了满足条件的环内的点的个数
97 0
[UVA1364 | POJ | NC]Knights of the Round Table | Tarjan 求点双 | 二分图 | 综合图论
|
机器学习/深度学习 人工智能 算法
[洛谷] [NOIP2018 提高组] 旅行 加强版 - 基环树 | DFS / Tarjan / topoSort
题目描述 小 Y 是一个爱好旅行的 OIer。她来到 X 国,打算将各个城市都玩一遍。 小Y了解到, X国的 n 个城市之间有 m 条双向道路。每条双向道路连接两个城市。 不存在两条连接同一对城市的道路,也不存在一条连接一个城市和它本身的道路。并且, 从任意一个城市出发,通过这些道路都可以到达任意一个其他城市。小 Y 只能通过这些 道路从一个城市前往另一个城市。
92 0
[洛谷] [NOIP2018 提高组] 旅行 加强版 - 基环树 | DFS / Tarjan / topoSort
|
机器学习/深度学习
[Nowcoder | UPC] 2021年度训练联盟热身训练赛第六场 Hopscotch | 最短路 bfs
题目描述 There’s a new art installation in town, and it inspires you… to play a childish game. The art installation consists of a floor with an n×n matrix of square tiles. Each tile holds a single number from 1 to k. You want to play hopscotch on it.
93 0