zoukankan      html  css  js  c++  java
  • 2017四川省赛D题《Dynamic Graph》

    题意:给出一个n个点m条边的有向无环图(DAG),初始的时候所有的点都为白色。然后有Q次操作,每次操作要把一个点的颜色改变,白色<->黑色,对于每次操作,输出满足下列点对<u,v>,u,v都为白色且可以相互到达的个数。

    数据范围:

    DAG上的问题,首先最暴力的方法就是,对于每一次更改都进行一遍dfs,B[u][v],表示U点可以到达v点,然后对于U的父亲结点来说,暴力合并,复杂度约为n^4,这样显然会爆炸。解法是每次用BITSET优化,因为B[u][v]的状态非零即一。

    代码如下:

    #include<bits/stdc++.h>
    typedef long long LL;
    using namespace std;
    const int maxn = 350;
    int N, M, Q;
    struct Edge
    {
        int to, next;
        Edge(int to = 0, int next = 0): to(to), next(next) {}
    } E[maxn * maxn];
    int head[maxn], tot;
    void initedge()
    {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void addedge(int u, int v)
    {
        E[tot] = Edge(v, head[u]);
        head[u] = tot++;
    }
    bitset<maxn>BT[maxn];
    int vis[maxn], cul[maxn];
    void init()
    {
        for(int i = 0; i <= N; i++)
        {
            BT[i].reset();
            vis[i] = cul[i] = 0;
        }
    }
    void DFS(int u)
    {
        BT[u].reset();
        BT[u][u] = 1;
        vis[u] = 1;
        if(cul[u]) return ;
        for(int k = head[u]; ~k; k = E[k].next)
        {
            int v = E[k].to;
            if(!vis[v]) DFS(v);
            if(!cul[v]) BT[u] |= BT[v];
        }
    }
    int main ()
    {
        while(~scanf("%d %d %d", &N, &M, &Q))
        {
            init();
            initedge();
            for(int i = 1; i <= M; i++)
            {
                int u, v;
                scanf("%d %d", &u, &v);
                addedge(u, v);
            }
            for(int i = 1; i <= Q; i++)
            {
                int u, ans = 0;
                scanf("%d", &u);
                cul[u] ^= 1;
                for(int i = 1; i <= N; i++) vis[i] = 0;
                for(int i = 1; i <= N; i++)
                {
                    if(!vis[i]) DFS(i);
                    ans += BT[i].count() - 1;
                }
                printf("%d
    ", ans);
            }
        }
        return 0;
    }

    另外还有一种方法:

    维护F[u][v],表示u->v的路径条数,然后对于每次操作更新F[u][v]-+=F[u][x]*F[x][v],然后判断F[u][v]是否>0即可,这样做是对的,但是F[u][v]可能非常大,要用unsigned long long ,虽然unsigned long long 存不下,但是他有自动取模的功能,即使是这样也有可能出现F[u][v]之间有路径,但是取模后为0的情况,但是这个概率是很小的,unsigned long long 已经很大了,取模后出现零的情况应该不会被卡。unsigned int 也可以过。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long LL;
    const int maxn = 350;
    LL dp[maxn][maxn], vis[maxn];
    int N, M, Q;
    void init()
    {
        for(int i = 1; i <= N; i++)
        {
            vis[i] = 0;
            for(int j = 1; j <= N; j++)
                dp[i][j] = 0;
        }
    }
    int main ()
    {
        while(~scanf("%d %d %d", &N, &M, &Q))
        {
            init();
            for(int i = 1; i <= M; i++)
            {
                int u, v;
                scanf("%d %d", &u, &v);
                dp[u][v]++;
            }
            for(int k = 1; k <= N; k++ )
                for(int st = 1; st < k; st++)
                    for(int ed = k + 1; ed <= N; ed++)
                        dp[st][ed] += dp[st][k] * dp[k][ed];
            for(int i = 1; i <= Q; i++)
            {
                int u;
                scanf("%d", &u);
                if(vis[u] == 0)
                {
                    vis[u] = 1;
                    for(int st = 1; st < u; st++)
                        for(int ed = u + 1; ed <= N; ed++)
                            dp[st][ed] -= dp[st][u] * dp[u][ed];
                }
                else
                {
                    vis[u] = 0;
                    for(int st = 1; st < u; st++)
                        for(int ed = u + 1; ed <= N; ed++)
                            dp[st][ed] += dp[st][u] * dp[u][ed];
                }
                int ans = 0;
                for(int st = 1; st <= N; st++)
                {
                    if(vis[st]) continue;
                    for(int ed = st + 1; ed <= N; ed++)
                    {
                        if(vis[ed]) continue;
                        if(dp[st][ed] > 0) ans++;
                    }
                }
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
    

      

    想的太多,做的太少。
  • 相关阅读:
    Spring 中出现Element : property Bean definitions can have zero or more properties. Property elements correspond to JavaBean setter methods exposed by the bean classes. Spring supports primitives, refer
    java定时器schedule和scheduleAtFixedRate区别
    hql语句中的select字句和from 字句
    使用maven搭建hibernate的pom文件配置
    Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from http://repo.maven.apache.org/ maven2 was cached in the local repository, resolution will not be reattempted until the update interv
    对于文件File类型中的目录分隔符
    hibernate的事务管理和session对象的详解
    解决mac 中的myeclipse控制台中文乱码问题
    ibatis selectKey用法问题
    Java中getResourceAsStream的用法
  • 原文地址:https://www.cnblogs.com/pealicx/p/6994651.html
Copyright © 2011-2022 走看看