• 2017 多校4 Matching In Multiplication(二分图)


    Matching In Multiplication

    题解:
    首先如果一个点的度数为1,那么它的匹配方案是固定的,继而我们可以去掉这一对点。通过拓扑我们可以不断去掉所有度数为1的点。

    那么剩下的图中左右各有m个点,每个点度数都不小于2,且左边每个点度数都是2,而右侧总度数是2m,因此右侧只能是每个点度数都是2。这说明这个图每个连通块是个环,在环上间隔着取即可,一共两种方案。

    时间复杂度O(n)。

    比赛的时候已经想出做法了,然而实现的太慢了,时间不够了,最后看了题解才想到,哦,原来隔着取就好了,我还想着去求匹配,标记取边呢
    讲道理,这个时间卡得真紧,我写的挫,用vector居然过不去,改成用数组建边,队列手写才过去

    #include<bits/stdc++.h>
    #define LL long long
    #define P pair<int,int>
    using namespace std;
    const int mod = 998244353;
    const int N = 1e6 + 10;
    int read(){
        int x = 0;
        char c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
        return x;
    }
    struct Edge{
        int v,w,nxt;
        Edge(){};
    }ee[N * 2];
    int head[N],EN;
    int n;
    int d[N];
    int vis[N];
    int cnt;
    int e[N];
    int Q[N];
    void add(int u,int v,int w){
        ee[EN].v = v,ee[EN].w = w,ee[EN].nxt = head[u + n];
        head[u + n] = EN++;
        ee[EN].v = u + n,ee[EN].w = w,ee[EN].nxt = head[v];
        head[v] = EN++;
    }
    void init(){
        EN = 0;
        for(int i = 1;i <= 2 * n;i++) {
            vis[i] = d[i] = 0;
            head[i] = -1;
        }
    }
    void dfs(int u,int f){
        vis[u] = 1;
        bool flag = true;
        int p;
        for(int i = head[u];~i;i = ee[i].nxt){
            if(ee[i].v != f) p = ee[i].w;
            if(!vis[ee[i].v]){
                e[cnt++] = ee[i].w;
                flag = false;
                dfs(ee[i].v,u);
            }
        }
        if(flag){
            e[cnt++] = p;
        }
    }
    
    int main(){
    
        int T;
        T = read();
        while(T--){
            n = read();
            int u,v,w,v1,w1,v2,w2;
            init();
            for(int i = 1;i <= n;i++){
                v1 = read(),w1 = read(),v2 = read(),w2 = read();
                d[v1]++,d[v2]++;
                add(i,v1,w1);
                add(i,v2,w2);
            }
            int h = 0,t = 0;
            LL ans = 1;
            for(int i = 1;i <= n;i++){
                if(d[i] == 1) Q[t++] = i;
            }
            while(h < t){
                u = Q[h++];
                for(int i = head[u];~i;i = ee[i].nxt){
                    if(vis[ee[i].v]) continue;
                    ans = ans * ee[i].w % mod, v = ee[i].v;
                    break;
                }
                vis[u] = vis[v] = 1;
                for(int i = head[v];~i;i = ee[i].nxt){
                    if(!vis[ee[i].v] && --d[ee[i].v] == 1) Q[t++] = ee[i].v;
                }
            }
            for(int i = 1;i <= n;i++){
                if(!vis[i] && d[i] == 2){
                    cnt = 0;
                    dfs(i,-1);
                    LL res1 = 1,res2 = 1;
                    for(int j = 0;j < cnt;j+=2){
                        res1 = res1 * e[j] %  mod;
                        res2 = res2 * e[j+1] % mod;
                    }
                    ans = ans * (res1 + res2) % mod ;
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    sopt:一个简单的python最优化库
    条件GAN论文简单解读
    python PIL 图像处理库简介(一)
    python自动制作gif并添加文字
    github+hexo搭建博客
    haskell简明入门(一)
    DCGAN 代码简单解读
    手机浏览器 H5直播
    js获取网页的宽高
    vue 对象赋值 对象身上已经有了属性,但是视图层并没有更新该数据 问题
  • 原文地址:https://www.cnblogs.com/jiachinzhao/p/7281886.html
Copyright © 2020-2023  润新知