hdu 4858 项目管理 图分治 (复合算法)

hdu 4858 项目管理

题意:给n(<=100000)个点,m条边( <=n+10),可能有重边,每个点有个值val,初识为0。

2种操作。

操作1:点x的值,加addx。

操作2:输出x点的邻点的val和。

分析:简单的优化操作1或操作2是不行的。

法一:针对点的度将图中点分为两类点。对于度大于sqrt (n)的点为重点,对于小于等于sqrt(n)的点为轻点。 重点的个数小于sqrt(n)个。针对重点和轻点分别处理。

法二:也可考虑每个点,将其邻点分类。大于该点度的点分为一类,等于该点的度的分为一类,小于该点的度的点分为一类。分别处理。

法一:

const int maxn = 100100;

vector<int>v[maxn], vgt[maxn];
int d[maxn];
int val[maxn];
int sum[maxn];
int n, m;
const int MM = 3333;

int main ()
{
    int T;
    cin >> T;
    while (T--)
    {
        scanf("%d%d", &n, &m);
        memset(d, 0, sizeof(d));
        memset(val, 0, sizeof(val));
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; i++)
        {
            v[i].clear(); vgt[i].clear();
        }
        for (int i = 0; i < m; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            v[x].push_back(y); v[y].push_back(x);
            d[x]++; d[y]++;
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 0; j < v[i].size(); j++)
            {
                int r = v[i][j];
                if (d[r] > MM) vgt[i].push_back(r);
            }
        }
        int Q;
        cin >> Q;
        while (Q--)
        {
            int op;
            int x, addx;
            scanf("%d", &op);
            if (!op)
            {
                scanf("%d%d", &x, &addx);
                val[x] += addx;
                if (d[x] <= MM)
                {
                    for (int i = 0; i < vgt[x].size(); i++)
                    {
                        int y = vgt[x][i];
                        sum[y] += addx;
                    }
                }
            }
            else
            {
                scanf("%d", &x);
                int ans = 0;
                if (d[x] <= MM)
                {
                    for (int i = 0; i < v[x].size(); i++)
                    {
                        ans += val[v[x][i]];
                    }
                }
                else
                {
                    ans += sum[x];
                    for (int i = 0; i < vgt[x].size(); i++)
                    {
                        int y = vgt[x][i];
                        ans += val[y];
                    }
                }
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}
/**
4

3 2
1 2
1 3
6
0 1 15
0 3 4
1 1
1 3
0 2 33
1 2

3 2
1 2
1 2
6
0 1 15
1 1
0 2 15
1 1
1 3

*/

法二:

const int maxn = 100100;

vector<int>v[maxn], vgt[maxn], veq[maxn];
int d[maxn];
int val[maxn];
int sum[maxn];
int n, m;
const int MM = 3333;

int main ()
{
    int T;
    cin >> T;
    while (T--)
    {
        scanf("%d%d", &n, &m);
        memset(d, 0, sizeof(d));
        memset(val, 0, sizeof(val));
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; i++)
        {
            v[i].clear(); vgt[i].clear(); veq[i].clear();
        }
        for (int i = 0; i < m; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            v[x].push_back(y); v[y].push_back(x);
            d[x]++; d[y]++;
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 0; j < v[i].size(); j++)
            {
                int r = v[i][j];
                if (d[r] > d[i]) vgt[i].push_back(r);
                else if (d[r] == d[i]) veq[i].push_back(r);
            }
        }
        int Q;
        cin >> Q;
        while (Q--)
        {
            int op;
            int x, addx;
            scanf("%d", &op);
            if (!op)
            {
                scanf("%d%d", &x, &addx);
                val[x] += addx;
                for (int i = 0; i < vgt[x].size(); i++)
                    sum[vgt[x][i]] += addx;
            }
            else
            {
                scanf("%d", &x);
                int ans = sum[x];
                for (int i = 0; i < vgt[x].size(); i++)
                    ans += val[vgt[x][i]];
                for (int i = 0; i < veq[x].size(); i++)
                    ans += val[veq[x][i]];
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}
/**
4

3 2
1 2
1 3
6
0 1 15
0 3 4
1 1
1 3
0 2 33
1 2

3 2
1 2
1 2
6
0 1 15
1 1
0 2 15
1 1
1 3

*/

hdu 4858 项目管理 图分治 (复合算法)

时间: 2024-08-04 10:44:25

hdu 4858 项目管理 图分治 (复合算法)的相关文章

hdu 4858 项目管理 图的分块

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的!两个节点间可能有多条边,不过一条边的两端必然是不同的节点.每个节点都有一个能量值.现在我们要编写一个项目管理软件,这个软件呢有两个操作:1.给某个项目的能量值加上一个特定值.2.询问跟一个项目相邻的项目的能量值之和.(如果有多条边就算多次,比如a和b有2条边,那么询问a的时候b的权值算2次). Input 第一行

hdu 4858 项目管理 (图的分治)

项目管理 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 252    Accepted Submission(s): 88 Problem Description 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的! 两个节点间可能有多条边,不过一条边的两端必然是不同的节点. 每个节点都有一个能量值. 现

HDU 4858 项目管理(邻接表 暴力模拟)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的! 两个节点间可能有多条边,不过一条边的两端必然是不同的节点.每个节点都有一个能量值. 现在我们要编写一个项目管理软件,这个软件呢有两个操作:1.给某个项目的能量值加上一个特定值.2.询问跟一个项目相邻的项目的能量值之和.(如果有多条边就算多次,比如a和b有2条边,那么询问a的时候b的权值算2次). 解题报告:这个

hdu 4858 项目管理(vector模拟)

# include <stdio.h> # include <algorithm> # include <string.h> # include <vector> # define N 100005 using namespace std; vector<int>g[N]; int node[N]; int slove(int x) { int sum=0,i; for(i=0;i<g[x].size();i++) { sum+=node[

hdu 4858 项目管理

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858 题意:中文不解释 解法:直接按题意模拟一遍,数据水? 代码: #include<stdio.h> #include<iostream> #include<math.h> #include<stdlib.h> #include<ctype.h> #include<algorithm> #include<vector> #i

hdu 4858 项目管理(STL集装箱)

项目管理 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 730    Accepted Submission(s): 258 Problem Description 我们建造了一个大项目! 这个项目有n个节点,用非常多边连接起来.而且这个项目是连通的! 两个节点间可能有多条边,只是一条边的两端必定是不同的节点. 每一个节点都有一个能量

BestCoder Round #1 1002 项目管理 (HDU 4858)

项目管理 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 738    Accepted Submission(s): 260 Problem Description 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的!两个节点间可能有多条边,不过一条边的两端必然是不同的节点.每个节点都有一个能量值. 现在我

zw&#183;准专利&#183;高保真二值图细部切分算法

zw·准专利·高保真二值图细部切分算法     高保真二值图细部切分算法,是中国字体协会项目的衍生作品.     说准专利算法,是因为对于图像算法的标准不了解,虽然报过专利,但不是这方面的,需要咨询专业的专利顾问.     原型是用opencv+python实现的,因为Halcon,对于协会的设计师,门槛太高,所以,特意设计了一套opencv+python的live-cd,解压即可,无需配置. 中国传统书法,有很多飞白.泼墨的手法,产生了很多小孔.孤点,从图像学角度,这些都是细小的感染区. 传统

hdu 1162 Eddy&#39;s picture(最小生成树算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1162 Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6866    Accepted Submission(s): 3469 Problem Description Eddy begins to like p