zoukankan      html  css  js  c++  java
  • HDU

    博主的 BiBi 时间

    我真的 (mathtt{biiiiiii})

    我没有算空间复杂度就开始码,结果码了一个复杂度极高的算法,交上去就 (mathtt{MLE})(mathtt{QwQ})

    Code

    我们只算大部头(即建边的复杂度)的复杂度。

    (500*500*32*1*2=16000000=16000000*4/1024KB=62500KB),然而你可以发现 (mathtt{HDU}) 只开了三万多 (KB)

    炸了。。。

    下面是代码,如果开大了嘤该能过。

    Update:好吧其实开大了也过不了,题目还有一个坑:输入的 (b) 数组从 (0) 开始!!!

    #include <cstdio>
    #include <cstring>
    
    const int N = 32000, M = 3e6 + 500;
    
    int a[505][505], n, head[N], Head[N], be[N], scc[N], tot, cnt, to[M], nxt[M];
    bool vis[N];
    
    int read() {
        int x = 0, f = 1; char s;
        while((s = getchar()) > '9' || s < '0') if(s == '-') f = -1;
        while(s >= '0' && s <= '9') x = (x << 1) + (x << 3) + (s ^ 48), s = getchar();
        return x * f;
    }
    
    void addEdge(const int u, const int v) {
        to[++ cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
        to[++ cnt] = u, nxt[cnt] = Head[v], Head[v] = cnt;
    }
    
    void dfs1(const int u) {
        vis[u] = 1;
        for(int i = head[u]; i; i = nxt[i])
            if(! vis[to[i]]) dfs1(to[i]);
        scc[++ tot] = u;
    }
    
    void dfs2(const int u) {
        vis[u] = 1; be[u] = tot;
        for(int i = Head[u]; i; i = nxt[i])
            if(! vis[to[i]]) dfs2(to[i]);
    }
    
    void Kosaraju() {
        memset(vis, 0, sizeof vis); tot = 0;
        for(int i = 0; i < 64 * n; ++ i) if(! vis[i]) dfs1(i);
        memset(vis, 0, sizeof vis); tot = 0;
        for(int i = 64 * n - 1; ~i; -- i)
            if(! vis[scc[i]]) ++ tot, dfs2(scc[i]);
    }
    
    int main() {
        int len, x[35], p; bool flag;
        while(~ scanf("%d", &n)) {
            memset(head, 0, sizeof head); memset(Head, 0, sizeof Head); cnt = 0; flag = 0;
            for(int i = 1; i <= n; ++ i)
                for(int j = 1; j <= n; ++ j)
                    a[i][j] = read();
            for(int i = 1; i <= n; ++ i) {
                if(a[i][i]) {puts("NO"); flag = 1; break;}
                for(int j = 1; j <= n; ++ j)
                    if(a[i][j] != a[j][i]) {puts("NO"); flag = 1; break;}
            }
            if(flag) continue;
            for(int i = 1; i <= n; ++ i) {
                for(int j = i + 1; j <= n; ++ j) {
                    len = 0;
                    while(a[i][j]) x[++ len] = (a[i][j] & 1), a[i][j] >>= 1;
                    if((i & 1) && (j & 1)) {
                        for(int k = 1; k <= (len << 1); k += 2)
                            if(x[k] & 1) addEdge((i - 1) * 64 + k - 1, (j - 1) * 64 + k), addEdge((j - 1) * 64 + k - 1, (i - 1) * 64 + k);
                            else addEdge((i - 1) * 64 + k, (i - 1) * 64 + k - 1), addEdge((j - 1) * 64 + k, (j - 1) * 64 + k - 1);
                    }
                    else if(i % 2 == 0 && j % 2 == 0) {
                        for(int k = 1; k <= (len << 1); k += 2)
                            if(x[k] & 1) addEdge((i - 1) * 64 + k - 1, (i - 1) * 64 + k), addEdge((j - 1) * 64 + k - 1, (j - 1) * 64 + k);
                            else addEdge((i - 1) * 64 + k, (j - 1) * 64 + k - 1), addEdge((j - 1) * 64 + k, (i - 1) * 64 + k - 1);
                    }
                    else {
                        for(int k = 1; k <= (len << 1); k += 2) {
                            if(x[k] & 1) addEdge((i - 1) * 64 + k - 1, (j - 1) * 64 + k), addEdge((i - 1) * 64 + k, (j - 1) * 64 + k - 1),
                                         addEdge((j - 1) * 64 + k - 1, (i - 1) * 64 + k), addEdge((j - 1) * 64 + k, (i - 1) * 64 + k - 1);
                            else addEdge((i - 1) * 64 + k - 1, (j - 1) * 64 + k - 1), addEdge((i - 1) * 64 + k, (j - 1) * 64 + k),
                                 addEdge((j - 1) * 64 + k - 1, (i - 1) * 64 + k - 1), addEdge((j - 1) * 64 + k, (i - 1) * 64 + k);
                        }
                    }
                }
            }
            Kosaraju();
            for(int i = 0; i < n; ++ i)
                for(int j = 1; j <= 64; j += 2)
                    if(be[i + j - 1] == be[i + j] && be[i + j]) {flag = 1; break;}
            puts(flag ? "NO" : "YES");
        }
        return 0;
    }
    

    Solution

    其实想出正解有点骄傲(其实没什么骄傲的,我只是太蒻了)。

    我们可以枚举 (i,j),将 (b[i][j]) 二进制分解一位一位地做就行了(比如异或就是 (i)(1)(j) 就必须选 (0))。

    可以发现对于每个二进制位 (x),它的点都是可以独立跑的。我的空间复杂度高就高在我把每个二进制位的点都存了一遍,凭空乘了个 (32)。。。

    Code

    这道题的代码和 HDU - 3622 Bomb Game 是一样的坑,然后我又掉进去了。。。

    #include <cstdio>
    #include <cstring>
    
    const int N = 32000, M = 1e6 + 500;
    
    int a[505][505], n, head[N], Head[N], be[N], scc[N], tot, cnt, to[M], nxt[M];
    bool vis[N];
    
    int read() {
        int x = 0, f = 1; char s;
        while((s = getchar()) > '9' || s < '0') if(s == '-') f = -1;
        while(s >= '0' && s <= '9') x = (x << 1) + (x << 3) + (s ^ 48), s = getchar();
        return x * f;
    }
    
    void addEdge(const int u, const int v) {
        to[++ cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
        to[++ cnt] = u, nxt[cnt] = Head[v], Head[v] = cnt;
    }
    
    void dfs1(const int u) {
        vis[u] = 1;
        for(int i = head[u]; i; i = nxt[i])
            if(! vis[to[i]]) dfs1(to[i]);
        scc[++ tot] = u;
    }
    
    void dfs2(const int u) {
        vis[u] = 1; be[u] = tot;
        for(int i = Head[u]; i; i = nxt[i])
            if(! vis[to[i]]) dfs2(to[i]);
    }
    
    void Kosaraju() {
        memset(vis, 0, sizeof vis); tot = 0;
        for(int i = 0; i < (n << 1); ++ i) if(! vis[i]) dfs1(i);
        memset(vis, 0, sizeof vis); tot = 0;
        for(int i = (n << 1) - 1; ~i; -- i)
            if(! vis[scc[i]]) ++ tot, dfs2(scc[i]);
    }
    
    int main() {
        bool flag;
        while(~ scanf("%d", &n)) {
           	flag = 0;
            for(int i = 1; i <= n; ++ i)
                for(int j = 1; j <= n; ++ j)
                    a[i][j] = read();
            for(int i = 1; i <= n; ++ i) {
                if(a[i][i]) {puts("NO"); flag = 1; break;}
                for(int j = 1; j <= n; ++ j)
                    if(a[i][j] != a[j][i]) {puts("NO"); flag = 1; break;}
            }
            if(flag) continue;
            for(int k = 0; k < 31; ++ k) {
    			memset(head, 0, sizeof head); memset(Head, 0, sizeof Head); cnt = 0;
            	for(int i = 1; i <= n; ++ i) {
                	for(int j = i + 1; j <= n; ++ j) {
                		int bit = ((1 << k) & a[i][j]);
                    	if((i - 1 & 1) && (j - 1 & 1)) {
                            if(bit) addEdge(i - 1, j - 1 + n), addEdge(j - 1, i - 1 + n);
                            else addEdge(i - 1 + n, i - 1), addEdge(j - 1 + n, j - 1);
                    	}
                    	else if((i - 1) % 2 == 0 && (j - 1) % 2 == 0) {
                            if(bit) addEdge(i - 1, i - 1 + n), addEdge(j - 1, j - 1 + n);
                            else addEdge(i - 1 + n, j - 1), addEdge(j - 1 + n, i - 1);
                    	}
                    	else {
                            if(bit) addEdge(i - 1, j - 1 + n), addEdge(i - 1 + n, j - 1),
    							 addEdge(j - 1, i - 1 + n), addEdge(j - 1 + n, i - 1);
                            else addEdge(i - 1, j - 1), addEdge(i - 1 + n, j - 1 + n),
                                 addEdge(j - 1, i - 1), addEdge(j - 1 + n, i - 1 + n);
                        }
                    }
                }
                if(! cnt) break;
            	Kosaraju();
            	for(int i = 0; i < n; ++ i) if(be[i] == be[i + n]) {flag = 1; break;}
            	if(flag) break;
            }
    		puts(flag ? "NO" : "YES");
        }
        return 0;
    }
    
  • 相关阅读:
    TV 丽音(NICAM)功能
    TV TimeShift和PVR的区别
    VGA、DVI、HDMI三种视频信号接口
    单词记忆
    gdb调试的基本使用
    Shell中字符串的切割、拼接、比较、替换
    I2C通信基本原理及其实现
    为什么单片机需要时钟系统,时钟信号在单片机中扮演怎样的角色?
    HDMI热插拔检测原理
    HDMI接口之HPD(热拔插)
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/13160475.html
Copyright © 2011-2022 走看看