HDU 6072 Logical Chain (Biset+Kosaraju, 2017 Multi-Univ Training Contest 4)

来源:互联网 发布:游戏编程要学java 编辑:程序博客网 时间:2024/06/17 19:32

Problem

Every time you come across a problem you’ve never seen before, haven’t you thought of something that is familiar to you? If so, you might think of something else, then more and more things will come to your mind. This is what is called ”Logical Chain”. Lu Xun’s work also described such interesting phenomenon.

img

Assume there are n things, labeled by 1,2,…,n. Little Q’s mind can be expressed by a n×n matrix g. If he can think of j when he comes across i, then gi,j is 1, otherwise it’s 0. For two different things u and v, if u can lead to v directly or indirectly and v can also lead to u directly or indirectly, then the pair (u,v) is called a ”Looping Pair”.

Little Q’s mind changes all the time. On i-th day, there are ki positions (u,v) in matrix g flipped(0 to 1 and 1 to 0). Please write a program to figure out the number of ”Looping Pairs” after each day’s all changes.

Note : (u,v) and (v,u) should not be counted twice.

此题动态修改图 G 的边集,求每次修改后的 pt×(pt1)2 (记每个强连通分量中的点数量为 pt )。

其中修改操作共 m 次,每次最多改 k 条边。1m25000,1k10

图 G 中点数为 n ,1n250

Idea

此题动态修改图 G 的边集,求每次修改后的 pt×(pt1)2 (记每个强连通分量中的点数量为 pt )。

求强连通分量,已有的算法有 Tarjan O(V+E) , Kosaraju O(V+E) or O(V2) 。对于图中动态修改边集的情况,使用前向星或邻接表等可优化稀疏图的复杂度,但对于稠密图无解,同时,无法解决边集的动态更新问题。

使用邻接矩阵存储边集状态,利用 Kosaraju 解决的复杂度将达到 O(V2×M) 。故利用 BITSET 优化边集的存储即 DFS 的后续点查找。复杂度 O(V2×M32)

Code

#include<bits/stdc++.h>using namespace std;const unsigned MAXU = (1llu<<32) - 1;const int N = 256;int T, n, m, k, u, v, rev[N], idx, cnt, ans;struct BITSET {    unsigned b[8];    int size;    void reset() {  memset(b, 0, sizeof(b));    }    void reset(int pos) {        b[pos>>5] &= MAXU ^ (1u<<(pos&31));    }    void set() {    memset(b, 0xff, sizeof(b)); }    void set(int pos) {        b[pos>>5] |= (1u<<(pos&31));    }    void flip(int pos) {        b[pos>>5] ^= (1u<<(pos&31));    }    bool test(int pos) {        return b[pos>>5] & (1u<<(pos&31));    }} g[N], gt[N], vis;char s[N];void dfs(int rt) {    if(vis.test(rt))    return;    vis.set(rt);    for(int i=0;i<8;i++)        while(true) {            unsigned x = g[rt].b[i] - (g[rt].b[i] & vis.b[i]);            if(!x)  break;            dfs((i<<5) | (__builtin_ctz(x)));        }    rev[++idx] = rt;}void rev_dfs(int rt) {    vis.flip(rt);    cnt++;    for(int i=0;i<8;i++)        while(true) {            unsigned x = gt[rt].b[i] - (gt[rt].b[i] & vis.b[i]);            if(!x)  break;            rev_dfs((i<<5) | (__builtin_ctz(x)));        }}void kosaraju() {    ans = 0;        vis.reset();    vis.set(0);    for(int i=n+1;i<256;i++)        vis.set(i);    idx = 0;    for(int i=1;i<=n;i++)        if(!vis.test(i))            dfs(i);    vis.reset();    vis.set(0);    for(int i=n+1;i<256;i++)        vis.set(i);    for(idx=n;idx;idx--)    {        if(vis.test(rev[idx]))  continue;         cnt = 0;        rev_dfs(rev[idx]);        ans += cnt * (cnt-1) / 2;    }}int main(){    scanf("%d", &T);    while(T-- && scanf("%d %d", &n, &m)!=EOF)    {        for(int i=1;i<=n;i++)            g[i].reset(),   gt[i].reset();        for(int i=1;i<=n;i++)        {            scanf(" %s", s+1);            for(int j=1;j<=n;j++)                if(s[j] == '1') {                     g[i].set(j);                    gt[j].set(i);                }        }        while(m-- && scanf("%d", &k))        {            for(int i=1;i<=k;i++)            {                scanf("%d %d", &u, &v);                g[u].flip(v);                gt[v].flip(u);            }            kosaraju();            printf("%d\n", ans);         }    }}
阅读全文
0 0
原创粉丝点击