zoukankan      html  css  js  c++  java
  • HDU 4858

    项目管理

    给一个n(不超过10^5)个点,m(不超过n+10)条边的点带权图,有两种操作:1、将某点权值增加;2、询问与某点直接相连的点的权值和。操作次数范围题目没有给出。

    【图的分块】称度大于sqrt(n)的点为重点,其余为轻点。由于度数最多为2*m,所以重点不超过2*sqrt(n)个。先算sum[],sum[i]表示与点i相连的轻点的权值和。

    对操作1,如果它是轻点,直接O(sqrt(n))更改所有与其相连的点的sum[],如果是重点,那么O(1)更改其点权即可。

    对操作2,与其相连的轻点权值和为sum[],然后再O(sqrt(n))访问所有与其相连的重点(这里需要预处理求出每个点的重点)求权值和。总的来说,每个操作复杂度都是sqrt(n)。

    From here

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<string>
    #include<sstream>
    #define eps 1e-9
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define FOR(i,j,k) for(int i=j;i<=k;i++)
    #define clr(i,j) memset(i,j,sizeof(i))
    #define MAXN 100005
    #define MAXM 300005
    #define INF 0x3fffffff
    using namespace std;
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num;
    bool flag;
    
    int edge,deg[MAXN],sum[MAXN],w,q,u,v,value[MAXN];
    
    vector <int> G[MAXN],HG[MAXN];
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            clr(deg,0);
            clr(sum,0);
            clr(value,0);
            edge=0;
            
            scanf("%d%d",&n,&m);
            for (i=1;i<=n;i++) G[i].clear();
            for (i=1;i<=m;i++)//使用邻接表读入 
            {
                scanf("%d%d",&x,&y);
                G[x].push_back(y);
                G[y].push_back(x);
                deg[x]++;deg[y]++;
            }
            
            int d=(int)(sqrt(n)+eps); 
            
            for (i=1;i<=n;i++)//预处理与每个点相邻的重点列表 
            {
                HG[i].clear();
                for (j=0;j<G[i].size();j++)
                {
                    if ( deg[ G[i][j] ] > d ) HG[i].push_back(G[i][j]);
                }
            }
            
            scanf("%d",&q);
            for (i=1;i<=q;i++)
            {
                int ch;
                scanf("%d",&ch);
                if (ch==0)
                {
                    scanf("%d%d",&u,&w);
                    if (deg[u]<=d)//轻点 
                    {
                        for (j=0;j<G[u].size();j++)
                        {
                            sum[ G[u][j] ]+=w;
                        }
                    }else//重点
                    {
                        value[u]+=w;
                    }
                }else
                {
                    scanf("%d",&u);
                    ans=sum[u];//这是周围轻点的权值和 
                    for (j=0;j<HG[u].size();j++)//再枚举每个重点的权值,累加 
                    {
                        ans+=value[ HG[u][j] ]; 
                    }
                    printf("%d
    ",ans);
                }
            }
        }
    }
  • 相关阅读:
    mybatis 查询一对多子表只能查出一条数据
    Docker 查看容器里Log4写的日 志文 件里的日志
    MYSQL之union的使用
    【前端开发】常见好用的流程图框架
    【推荐】好网站推荐
    【前端工具】好用的数据库工具Navicat
    jQuery ajax
    thinkphp6.0封装数据库及缓存模型
    Unity 3D使用C#脚本实例
    Unity 3D简单使用C#脚本,脚本的执行顺序
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4263410.html
Copyright © 2011-2022 走看看