Graph

Problem Description

P. T. Tigris is a student currently studying graph theory. One day, when he was studying hard, GS appeared around the corner shyly and came up with a problem:
Given a graph with n nodes and m undirected weighted edges, every node having one of two colors, namely black (denoted as 0) and white (denoted as 1), you’re to maintain q operations of either kind:

* Change x: Change the color of x
th node. A black node should be changed into white one and vice versa.

* Asksum A B: Find the sum of weight of those edges whose two end points are in color A and B respectively. A and B can be either 0 or 1.

P. T. Tigris doesn’t know how to solve this problem, so he turns to you for help.
 
Input
There are several test cases.

For each test case, the first line contains two integers, n and m (1 ≤ n,m ≤ 10
5), where n is the number of nodes and m is the number of edges.

The second line consists of n integers, the i
th of which represents the color of the i
th node: 0 for black and 1 for white.

The following m lines represent edges. Each line has three integer u, v and w, indicating there is an edge of weight w (1 ≤ w ≤ 2
31 - 1) between u and v (u != v).

The next line contains only one integer q (1 ≤ q ≤ 10
5), the number of operations.

Each of the following q lines describes an operation mentioned before.

Input is terminated by EOF.
 
Output
For each test case, output several lines.

The first line contains “Case X:”, where X is the test case number (starting from 1).

And then, for each “Asksum” query, output one line containing the desired answer.
 
Sample Input
4 3
0 0 0 0
1 2 1
2 3 2
3 4 3
4
Asksum 0 0
Change 2
Asksum 0 0
Asksum 0 1
4 3
0 1 0 0
1 2 1
2 3 2
3 4 3
4
Asksum 0 0
Change 3
Asksum 0 0
Asksum 0 1
 
Sample Output
Case 1:
6
3
3
Case 2:
3
0
4
这题是很好的题啊,题目意思就是,给一些点,都是0或1,找两边是00 01 11的边权合,这题的关键就是有的边很多,如果我们就用暴力,那么复杂度必然是p*n,其实,想想问题的关键,就是有的点相连的边太多了,这样暴力会超时,比赛的时候,也是这个问题,虽然有点想法,但当时由于时间太短,不能写出来,下来要想了很长时间,我们要把有很多的边标记下,特殊处理,这样,我们不就能省掉很多时间了么?基于,这样的想法,我们,就可以这样做,把超过界限的点,标记成超极点,其他的就是普通点,我们连接超极点和超极点,普通点与普通点。超极点,但是,超极点不连接普通点!对于超极点,我们用一个数组,保存它周围的0和1的点的权和,这样我们就可以用0(1)的时间,快速维护最终的结果,对于普通点,我们就暴力维护就可以了,因为他周围的点少,时间就可以大大的省下来!这样的想法很好,复杂度是多少呢?我们可以发现,如果我们把办限定为sqrt(m),那么超极点的个数一定不会多于2*sqrt(m),这一点很好证明,那么这样,所有点的暴力维护的值都是sqrt(m)了,那么复杂度就是n*sqrt(m),当然,这是可以过了的,这种思想很有用,也很神奇啊,当时,有点影子,但没有时间,来实现了!对于本题一定要注意重边的情况和一定要用--int64,好了,到这里,就可以a了!还有一点小技巧,见代码!
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAXN 100005
struct nodeedge{
int s,e;
__int64 val;
}edge[40*MAXN];
struct nodelist{
int next,to,flag;
}l[200*MAXN];
char str[300];
int head[MAXN],p[MAXN],index[MAXN],limit;//判定是否是超极点
__int64 sum[3],sumsuper[MAXN][2];
void change(int x)
{
int i,j;
int temp=p[x]^1,t; for(j=head[x];j!=-1;j=l[j].next)
{
i=l[j].to;
sum[p[x]+p[i]]-=edge[j].val;
sum[temp+p[i]]+=edge[j].val;
if((!l[x].flag)&&l[i].flag)
{
sumsuper[i][p[x]]-=edge[j].val;
sumsuper[i][temp]+=edge[j].val;
}
}
if(l[x].flag)
{
sum[p[x]]-=sumsuper[x][0];
sum[temp]+=sumsuper[x][0];
sum[p[x]+1]-=sumsuper[x][1];
sum[temp+1]+=sumsuper[x][1];
}
p[x]=p[x]^1;//取反
}
void build(int i,int s,int e,__int64 val)//建邻接表
{
if(l[s].flag&&(!l[e].flag))
{
sumsuper[s][p[e]]+=val;
}
else
{
l[i].next=head[s];
l[i].to=e;
head[s]=i;
}
}
bool cmp(nodeedge a,nodeedge b)
{
if(a.s != b.s)
return a.s < b.s;
else
return a.e < b.e;
}
int main ()
{
int n,m,i,edgem,m2,asnum,a1,a2,tcase;
tcase=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
limit=350;m2=2*m;
sum[0]=sum[1]=sum[2]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
index[i]=0;head[i]=-1;
}
for(i=1;i<=m;i++)
{
scanf("%d%d%I64d",&edge[i].s,&edge[i].e,&edge[i].val);
edge[i+m].s=edge[i].e,edge[i+m].e=edge[i].s,edge[i+m].val=edge[i].val;//建反向边
sum[p[edge[i].s]+p[edge[i].e]]+=edge[i].val;
}
sort(edge+1,edge+m2+1,cmp);//边从1开始计数
edgem=1;
for(i=2;i<=m2;i++)//去掉重边
{
if((edge[i].s==edge[edgem].s)&&(edge[i].e==edge[edgem].e))
{
edge[edgem].val+=edge[i].val;
}
else{
edgem++;
edge[edgem]=edge[i];
}
}
for(i=1;i<=edgem;i++)
{
index[edge[i].s]++;
}
for(i=1;i<=n;i++)//统计超极结点
{
if(index[i]>=limit)
{
l[i].flag=1;//是超极结点
sumsuper[i][0]=sumsuper[i][1]=0;
} else
l[i].flag=0;
} for(i=1;i<=edgem;i++)//建领接表
{
build(i,edge[i].s,edge[i].e,edge[i].val);
}
scanf("%d",&asnum);
printf("Case %d:\n",tcase++);
while(asnum--)
{
scanf("%s",str);
if(str[0]=='A')
{
scanf("%d%d",&a1,&a2);
printf("%I64d\n",sum[a1+a2]);
}
else{
scanf("%d",&a1);
change(a1);
}
} }
return 0;
}

hdu4467 Graph的更多相关文章

  1. HDU4467:Graph(点的度数分块)

    传送门 题意 给出一张n个点m条边的无向图,点的颜色为0/1,每次有两种操作: 1.Asksum x y,查询两点颜色为x和y的边的权值之和 2.Change x,将x颜色取反 分析 最直接的做法是每 ...

  2. HDU4467 Graph【轻重点维护】

    HDU4467 Graph 题意: 给出一张染色图,\(n\)个点每个点是黑色或者白色,\(m\)条带权边,\(q\)次操作,有两种操作: 改变一个点的颜色 问所有边中两个端点的颜色为给定情况的边权和 ...

  3. [开发笔记] Graph Databases on developing

    TimeWall is a graph databases github It be used to apply mathematic model and social network with gr ...

  4. Introduction to graph theory 图论/脑网络基础

    Source: Connected Brain Figure above: Bullmore E, Sporns O. Complex brain networks: graph theoretica ...

  5. POJ 2125 Destroying the Graph 二分图最小点权覆盖

    Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2 ...

  6. [LeetCode] Number of Connected Components in an Undirected Graph 无向图中的连通区域的个数

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  7. [LeetCode] Graph Valid Tree 图验证树

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  8. [LeetCode] Clone Graph 无向图的复制

    Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's ...

  9. 讲座:Influence maximization on big social graph

    Influence maximization on big social graph Fanju PPT链接: social influence booming of online social ne ...

随机推荐

  1. Spark笔记之DataFrameNaFunctions

    DataFrameNaFunctions用来对DataFrame中值为null或NaN的列做处理,处理分为三种类型: drop:根据条件丢弃含有null或NaN的行 fill:根据条件使用指定值填充值 ...

  2. 深入了解mitmproxy(二)

    主题    修改request或者response内容 介绍   mitmdump无交互界面的命令,与python脚本对接,来源于mitmproxy支持inline script,这里的script指 ...

  3. WPF的EventAggregator的发布和订阅

    EventAggregator是Prism中专门处理ViewModel与ViewModel之间事件传递的类对象,它提供了针对事件的发布方法和订阅方法,所以可以非常方便的来管理事件.下面分几步来实现相关 ...

  4. poj1221

    dp #include <cstdio> #include <cstring> #include <algorithm> using namespace std; ...

  5. ntpdate时间同步

    为什么需要网络同步时间: Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等操作时对多台机器的时间差是有要求的,此时就需要使用nt ...

  6. Java Scanner Readable

    通过implements(实现)Readbale interface(接口)的 read() method(方法) 实现自己添加字符到buffer里,然后读取 //策略模式package object ...

  7. java判断部署项目使用的服务器类型

    有两种方式 1.项目引入portal-kernel.jar.项目运行时使用 根据返回boolean值判断类型! 2.自己写java类 package webService.ZFGX.service; ...

  8. yum命令简介

    yum 一些较常见的用法 命令 功能 yum check-update 检查可更新的所有软件包 yum update 下载更新系统已安装的所有软件包 yum upgrade 大规模的版本升级,与yum ...

  9. Codeforces 405E Graph Cutting

    Graph Cutting 不会写.. dfs的过程中把回边丢到它的祖先中去, 回溯的时候两两配对.感觉好神奇啊. #include<bits/stdc++.h> #define LL l ...

  10. Pandas常用命令

    一.数据导入和导出 (一)读取csv文件 1.本地读取 import pandas as pd df = pd.read_csv('tips.csv') #根据自己数据文件保存的路径填写(p.s. p ...