• 《HDU多校第三场》


    Little W and Contest

    思路:首先很显然是并查集去维护答案。

    一开始,所有点都是独立的。那么设CF1 = 1的总个数。CF2 = 2的总个数

    那么一开始ans = C(CF1,1)*C(CF2,2)+C(CF2,3).

    那么考虑合并后怎么维护答案。

    这里运用了容斥思想。

    当我们合并后。我们只需要将之前合法的,现在不合法的答案删去即可。

    那么对于不合法的答案:肯定是这两个连通块各选一个,然后和剩下的所有组合。

    设合并的两个连通块为x,y。

    那么不合法的答案为。

    1.C(x2,1)*C(y2,1)*C(除x,y之外的1,1)

    2.C(x2,1)*C(y2,1)*C(除x,y之外的2,1)

    3.C(x2,1)*C(y1,1)*C(除x,y之外的2,1)

    4.C(x1,1)*C(y2,1)*C(除x,y之外的2,1)

    删完之后注意合并连通块里的数目

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<int,int> pii;
    const int N = 1e5+5;
    const int M = 250005;
    const LL Mod = 1e9+7;
    #define pi acos(-1)
    #define INF 1e8
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    LL a[N],x[N],y[N],f[N];//x - 2 ,y - 1.
    int fa[N];
    void init()
    {
        f[0] = 1;for(int i = 1;i < N;++i) f[i] = f[i-1]*i%Mod;
    }
    int Find(int x)
    {
        return x == fa[x] ? x : fa[x] = Find(fa[x]);
    }
    LL quick_mi(LL a,LL b)
    {
        LL re = 1;
        while(b)
        {
            if(b&1) re = (re*a)%Mod;
            a = (a*a)%Mod;
            b >>= 1;
        }
        return re;
    }
    LL inv(LL n){return quick_mi(n,Mod-2)%Mod;}
    LL C(LL n,LL m)
    {
        return f[n]*inv(f[n-m])%Mod*inv(f[m])%Mod;
    }
    int main()
    {
        init();
        int ca;ca = read();
        while(ca--)
        {
            int n;n = read();
            memset(x,0,sizeof(x));//2
            memset(y,0,sizeof(y));//1
            int cnt1 = 0,cnt2 = 0;//1,2
            for(int i = 1;i <= n;++i) 
            {
                a[i] = read(),fa[i] = i;
                if(a[i] == 1) y[i]++,cnt1++;
                else x[i]++,cnt2++;
            }
            LL ans = (C(cnt2,2)*C(cnt1,1)%Mod+C(cnt2,3))%Mod;
            printf("%lld\n",ans);
            for(int i = 1;i < n;++i)
            {
                int u,v;u = read(),v = read();
                int xx = Find(u),yy = Find(v);
                int z1 = cnt1-y[xx]-y[yy];
                int z2 = cnt2-x[xx]-x[yy];
                LL ma1,ma2,ma3,ma4;
                if(x[xx] > 0 && x[yy] > 0)//2 2 1
                {
                    ma1 = C(x[xx],1)*C(x[yy],1)%Mod*z1%Mod;
                    ans = ((ans-ma1)%Mod+Mod)%Mod;
                }
                if(x[xx] > 0 && y[yy] > 0)//2 1 2
                {
                    ma2 = C(x[xx],1)*C(y[yy],1)%Mod*z2%Mod;
                    ans = ((ans-ma2)%Mod+Mod)%Mod;
                }
                if(x[xx] > 0 && x[yy] > 0)//2 2 2
                {
                    ma3 = C(x[xx],1)*C(x[yy],1)%Mod*z2%Mod;
                    ans = ((ans-ma3)%Mod+Mod)%Mod;
                }
                if(y[xx] > 0 && x[yy] > 0)///1 2 2
                {
                    ma4 = C(y[xx],1)*C(x[yy],1)%Mod*z2%Mod;
                    ans = ((ans-ma4)%Mod+Mod)%Mod;
                }
                fa[xx] = yy;//合并
                x[yy] += x[xx];
                y[yy] += y[xx];
                printf("%lld\n",ans);
            }
        }
        system("pause");
        return 0;
    }
    View Code

    Tokitsukaze and Rescue

    思路:首先删的边肯定是最短路上的边。

    dfs枚举删除最短路上的每条边。

    每次删完边后都要跑dij来形成新的最短路。

    这里因为每次跑最短路之后pre数组会改变,那么可能影响到上层的pre数组。

    所以把pre数组开到dfs局部,这样就互不影响。

    因为这里是随机数据,可以猜想形成最短路的边不会特别多,这样可以保证每次枚举删边的边不会很多。

    考虑一下平均10条,k最大5,最坏复杂度为5^10左右。

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<int,int> pii;
    const int N = 55;
    const int M = 250005;
    const LL Mod = 1e9+7;
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    int n,k;
    LL dis[N],road[N][N],ans;
    void dij(int *pre)
    {
        for(int i = 1;i <= n;++i) dis[i] = INF;
        dis[1] = 0;
        priority_queue<pii,vector<pii>,greater<pii> > Q;
        Q.push(pii{0,1});
        pre[1] = 0;
        while(!Q.empty())
        {
            int u = Q.top().second;
            LL d = Q.top().first;
            Q.pop();
            if(d > dis[u]) continue;
            for(int i = 1;i <= n;++i)
            {
                if(dis[i] > dis[u]+road[u][i])
                {
                    pre[i] = u;
                    dis[i] = dis[u]+road[u][i];
                    Q.push(pii{dis[i],i});
                }
            }
        }
    }
    void dfs(int num)
    {
        int pre[N];
        dij(pre);
        if(num == k+1)
        {
            ans = max(ans,dis[n]);
            return ;
        }
        int now = n;
        while(now != 1)
        {
            LL tmp = road[now][pre[now]];
            road[now][pre[now]] = road[pre[now]][now] = INF;
            dfs(num+1);
            road[now][pre[now]] = road[pre[now]][now] = tmp;
            now = pre[now];
        }
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            n = read(),k = read();
            for(int i = 1;i <= n;++i)
                for(int j = 1;j <= n;++j) road[i][j] = INF;
            ans = -1;
            for(int i = 1;i <= n*(n-1)/2;++i)
            {
                int u,v,w;
                u = read(),v = read(),w = read();   
                road[u][v] = road[v][u] = w;
            }
            dfs(1);
            printf("%lld\n",ans);
        }
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    十二招让你的电脑桌变得更舒适
    【看后请推荐】程序员接私单不传秘籍之一二合编:加料更新!一定要看!
    【看后请推荐】程序员接私单不传秘籍之二:单子从哪儿来?
    【看后请推荐】程序员接私单不传秘籍之一:准备工作
    【看完请推荐】记国庆前的一次码农受骗记
    优化MySQL,还是使用缓存?读一篇文章有感
    大数据下Limit使用(MySQL)
    类Unix平台程序调试
    STL学习笔记
    MFC学习笔记
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13395059.html
Copyright © 2020-2023  润新知