• 集训Day6


    今天的图论题略多

    但好像都是noip题

    bzoj3624

    有一个图,边是黑色或者白色,求一个生成树满足恰好有k条白边

    贪心

    我们把最小生成树上的白边叫做“富家子弟”,把不在树上的叫“贫下中农”

    很明显,如果富家子弟超过k个,无解

    否则我们先记录富家子弟,然后加入若干贫下中农直至有k条白边

    然后加入剩下的黑边让图连通即可

    bzoj4596

    一个不超过17个点的无重边无自环的图

    每个公司可以建一个集合里的边

    一共n个点n个公司

    求一个生成树满足这n-1个点分别由n-1个公司建成

    矩阵树板子题

    考虑容斥原理

    答案为

    [最小生成树的数量]-[一个公司没有建的数量]+[两个公司没有建的数量] ... 

    二进制枚举一下就可以了,毕竟17

    bzoj3007

    一个$r imes c$的矩形

    从$(1,1)$走一条路径到$(r,c)$

    这个矩形里有n个boss,你的路径要满足离boss的最近距离最远

    $n leq 3000$

    首先,根据题目描述我们可以二分答案/滑稽

    我们二分到一个mid就是以所有boss为圆心,mid为半径画一个圆

    用最小割思想建出对偶图(反向对偶¿

    原图矩形左下到右上连通等价于对偶图里左下到右上不连通

    我们用画出的圆做一下noip2017D2T1的并查集就可以了

    (我没见过自己鞭尸自己的

    #include <iostream>
    #include <cstdio>
    #include <cctype>
    using namespace std;
    const int maxn = 20020;
    const int maxm = 100010;
    int n, m, k, fa[maxn], cnt0, cnt1, num;
    bool chs[maxm];
    struct edge
    {
        int u, v, c;
    } e[maxm];
    
    inline int read()
    {
        int x=0,f=1;char ch;
        for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
        for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
        return x*f;
    }
    
    int find(int u)
    {
        return fa[u] == u ? u : fa[u] = find(fa[u]);
    }
    
    int main()
    {
        n = read();
        m = read();
        k = read();
        for (int i = 1; i <= n; i++) fa[i] = i;
        for (int i = 1; i <= m; i++)
        {
            e[i].u = read();
            e[i].v = read();
            e[i].c = read();
        }
        for (int i = 1; i <= m; i++)
        {
            if (e[i].c == 1)
            {
                int r1 = find(e[i].u);
                int r2 = find(e[i].v);
                if (r1 != r2)
                {
                    fa[r1] = r2;
                    ++cnt1;
                }
            }
        }
        for (int i = 1; i <= m; i++)
        {
            if (e[i].c == 0)
            {
                int r1 = find(e[i].u);
                int r2 = find(e[i].v);
                if (r1 != r2)
                {
                    chs[i] = 1;
                    fa[r1] = r2;
                    ++cnt0;
                }
            }
        }
        if (cnt0 + cnt1 != n - 1 || cnt0 > k)
        {
            printf("no solution
    ");
            return 0;
        }
        for (int i = 1; i <= n; i++) fa[i] = i;
        cnt0 = cnt1 = 0;
        for (int i = 1; i <= m; i++)
        {
            if (chs[i])
            {
                int r1 = find(e[i].u);
                int r2 = find(e[i].v);
                if (r1 != r2)
                {
                    fa[r1] = r2;
                    ++cnt0;
                }
            }
        }
        for (int i = 1; i <= m; i++)
        {
            if (e[i].c == 0 && cnt0 < k)
            {
                int r1 = find(e[i].u);
                int r2 = find(e[i].v);
                if (r1 != r2)
                {
                    chs[i] = 1;
                    fa[r1] = r2;
                    ++cnt0;
                }
            }
        }
        if (cnt0 != k)
        {
            printf("no solution
    ");
            return 0;
        }
        for (int i = 1; i <= m; i++)
        {
            if (e[i].c == 1)
            {
                int r1 = find(e[i].u);
                int r2 = find(e[i].v);
                if (r1 != r2)
                {
                    chs[i] = 1;
                    fa[r1] = r2;
                }
            }
        }
        for (int i = 1; i <= m; i++)
            if (chs[i])
                printf("%d %d %d
    ", e[i].u, e[i].v, e[i].c);
        return 0;
    }
    T1
    #include<bits/stdc++.h>
    #define LL LL
    using namespace std;
    const int N=405,M=25;
    const int mod=1e9+7;
    struct node{int x,y;}t[M][N];
    LL C[M][M];int m[M];
    LL Guass(int n)
    {
        LL ans=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                LL a=C[i][i],b=C[j][i];
                while(b)
                {
                    LL temp=a/b;a%=b;swap(a,b);
                    for(int k=i;k<=n;k++) C[i][k]=(C[i][k]-temp*C[j][k]%mod+mod)%mod,swap(C[i][k],C[j][k]);
                    ans=-ans;
                }
            }
            if(!C[i][i]) return 0;
            ans=ans*C[i][i]%mod;
        }
        ans=(ans%mod+mod)%mod;
        return ans;
    }
    int main()
    {
        int n;scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            scanf("%d",&m[i]);
            for(int j=1;j<=m[i];j++) scanf("%d%d",&t[i][j].x,&t[i][j].y);
        }
        LL ans=0;
        for(int i=0;i<(1<<n-1);i++)
        {
            memset(C,0,sizeof(C));
            int num=0;
            for(int j=1;j<n;j++)
            {
                if(!(i&(1<<j-1))) continue;
                num++;
                for(int k=1;k<=m[j];k++)
                {
                    int a=t[j][k].x,b=t[j][k].y;
                    C[a][b]--;C[b][a]--;
                    C[a][a]++;C[b][b]++;
                }
            }
            if((n-1-num)%2) ans-=Guass(n-1);
            else ans+=Guass(n-1);
            ans=(ans%mod+mod)%mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    T2
    #include <bits/stdc++.h>
    #define N 3010
    using namespace std;
    int f[N];
    double x[N] , y[N];
    int find(int x)
    {
        return x == f[x] ? x : f[x] = find(f[x]);
    }
    void merge(int x , int y)
    {
        int tx = find(x) , ty = find(y);
        if(tx != ty) f[tx] = ty;
    }
    int main()
    {
        int n , i , j , cnt = 60;
        double a , b , l = 0 , r , mid;
        scanf("%d%lf%lf" , &n , &a , &b) , r = min(a , b);
        for(i = 1 ; i <= n ; i ++ ) scanf("%lf%lf" , &x[i] , &y[i]);
        while(cnt -- )
        {
            mid = (l + r) / 2;
            for(i = 0 ; i <= n + 1 ; i ++ ) f[i] = i;
            for(i = 1 ; i <= n ; i ++ )
            {
                if(mid >= x[i] - 1 || mid >= b - y[i]) merge(i , 0);
                if(mid >= a - x[i] || mid >= y[i] - 1) merge(i , n + 1);
                for(j = 1 ; j < i ; j ++ )
                    if((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) <= 4 * mid * mid)
                        merge(i , j);
            }
            if(find(0) == find(n + 1)) r = mid;
            else l = mid;
        }
        printf("%.2lf
    " , l);
        return 0;
    }
    T3
  • 相关阅读:
    C++ 对象没有显式初始化
    NFA与DFA
    VS DLL 复制本地
    TFS 图标意思
    C++ 析构方法
    C++ 异常
    【转】二叉树的非递归遍历
    【转】Dijkstra算法(单源最短路径)
    Dijkstra最短路径算法
    python __name__
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9200681.html
Copyright © 2020-2023  润新知