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 xth 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 ≤ 105), where n is the number of nodes and m is the number of edges.
The second line consists of n integers, the ith of which represents the color of the ith 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 ≤ 231 - 1) between u and v (u != v).
The next line contains only one integer q (1 ≤ q ≤ 105), 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 0、0 1、1 1 ,于是可以用三个变量ans[0]、ans[2]、ans[1],来记录总权值之和,遇到Asksum时直接输出就行了,遇到change时,则进行相关处理,来调整ans的值,最暴力

的方法就是将与x点相连的每条边和点进行处理,q*m的复杂付,无疑是超时的,我当时也就想到了这里,q肯定是不能优化了,

那么我们的优化对象就应该放在m上了,我当时有个想法,如果把每个点记录与之相连的点中,分别记录0和1 的权值之和,以w0和w1来表示。那么,该点改变时,例如:当当前点由0->1时,ans[0]-w[0],ans[1]+w[1],ans[2]-w[1]+w[0];  这样就是O(1)复杂度了,而且当前点得出的就结果是正确的。但是,当处理其他点时,其他点的w0和w1 没有给到更新,这显然是不行的,还需要再做些文章。说到这里,先说个结论,对于点x,与x相连并且度数大于x的度数的点不会超过(2m)^(1/2),这个证明很好证,可以自己去推下。接下来,我采取的方法是,用w0和w1表示度数比它小的权值之和,至于度数比它大,则逐边进行处理。这样复杂度是q*(m)^1/2,可以过。最后,我来说下这样为什么不会对其他点的更新造成影响。对于点x,度数大于它的是逐边处理的,点的信息也得到了更新;度数小于它的,信息则没有更新,那么,当处理到那些度数小的点时,也是按同样的方法在处理,度数大于的点逐边处理,这不就是把以前没有更新的过程给完成了吗?这样,就不会出现需要使用改点时,信息没得到完善。总而言之,就是利用度数形成一种顺序的结构,使其不会混乱。

# include<stdio.h>
# include<string.h>
# include<algorithm>
typedef __int64 ll; using namespace std;
struct node
{
int st;
ll w0,w1;
} p[100005];
struct edge
{
ll u,v;
ll w;
} e[100005],ed;
int color[100005],deg[100005];
ll ans[3];
bool cmp(edge x,edge y)
{
if (x.u>y.u) return true;
else return false;
}
int main()
{
int n,m,i,Case;
ll u,v,w;
char s[10];
Case=1;
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(deg,0,sizeof(deg));
for (i=1;i<=n;i++) scanf("%d",&color[i]);
for (i=1;i<=m;i++)
{
scanf("%I64d %I64d %I64d",&u,&v,&w);
e[i].w=w; e[i].v=v; e[i].u=u;
if (u>v)
{
ll tmp;
tmp=e[i].u;
e[i].u=e[i].v;
e[i].v=tmp;
}
}
sort(e+1,e+m+1,cmp); //使u<v,并按u排序,如此可快速判重边
int k=0;
for (i=2;i<=m;i++) //将重边合并
{
if (e[i].u==e[i-1].u&&e[i].v==e[i-1].v)
{
k++;
e[i-k].w+=e[i].w;
} else
{
e[i-k].w=e[i].w;
e[i-k].u=e[i].u;
e[i-k].v=e[i].v;
}
}
m-=k;
ans[0]=ans[1]=ans[2]=0;
for (i=1;i<=m;i++)
{
u=e[i].u; v=e[i].v;
deg[u]++; deg[v]++; //记录度数
if (color[u]!=color[v]) ans[2]+=e[i].w;
else ans[color[u]]+=e[i].w; //初始化三种情况的权值和
}
for (i=1;i<=m;i++)
{
u=e[i].u; v=e[i].v;
if (deg[u]>deg[v])
{
ll tmp;
tmp=e[i].u;
e[i].u=e[i].v;
e[i].v=tmp;
}
}
sort(e+1,e+m+1,cmp); //使u的度数小于v的度数,并排序,这样可以直接逐边处理
memset(p,0,sizeof(p));
for (i=1;i<=m;i++)
{
u=e[i].u; v=e[i].v;
if (p[u].st==0) p[u].st=i; //记录u节点第一次出现的位置
if (color[u]) p[v].w1=p[v].w1+e[i].w;
else p[v].w0=p[v].w0+e[i].w; //存储点的w0和w1
}
int q;
scanf("%d",&q);
printf("Case %d:\n",Case++);
while (q--)
{
int x,y;
scanf("%s",s);
if (s[0]=='A')
{
scanf("%d%d",&x,&y);
if (x!=y) printf("%I64d\n",ans[2]);
else printf("%I64d\n",ans[x]); //这里可以发现为什么ans的表示的巧妙
}
else
{
scanf("%d",&x);
if (color[x]) //处理小度数的
{
ans[2]=ans[2]+p[x].w1-p[x].w0;
ans[0]=ans[0]+p[x].w0;
ans[1]=ans[1]-p[x].w1;
}
else
{
ans[2]=ans[2]+p[x].w0-p[x].w1;
ans[0]=ans[0]-p[x].w0;
ans[1]=ans[1]+p[x].w1;
}
color[x]=1-color[x];
int st=p[x].st;
while (st<=m&&e[st].u==x) //大度数的
{
v=e[st].v;
if (color[x]!=color[v])
{
ans[2]+=e[st].w;
ans[1-color[x]]-=e[st].w;
}
else
{
ans[color[x]]+=e[st].w;
ans[2]-=e[st].w;
}
if (color[x]==0)
{
p[v].w0+=e[st].w;
p[v].w1-=e[st].w;
}
else
{
p[v].w0-=e[st].w;
p[v].w1+=e[st].w;
}
st++;
}
}
}
}
return 0;
}
/*
1、输出long long 变量时需要用%lld
2、注意在HDOJ上使用%I64d,但是现场赛使用%lld
*/

hdu 4467 Graph的更多相关文章

  1. HDU 4467 Graph(图论+暴力)(2012 Asia Chengdu Regional Contest)

    Description P. T. Tigris is a student currently studying graph theory. One day, when he was studying ...

  2. [la P5031&hdu P3726] Graph and Queries

    [la P5031&hdu P3726] Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: ...

  3. HDU 3726 Graph and Queries treap树

    题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...

  4. Graph HDU - 4467

    https://vjudge.net/problem/HDU-4467 大概就是,设一个块大小T 对于度数<=T的点,设为1类点,在改变颜色的时候暴力查询与其相邻点,更新答案 对于度数>T ...

  5. HDU 4467 分块

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: ...

  6. HDU 4034 Graph(Floyd变形——逆向判断)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4034 Problem Description Everyone knows how to calcu ...

  7. hdu 4034 Graph (floyd的深入理解)

    Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submi ...

  8. HDU 5607 graph(DP+矩阵乘法)

    [题目链接] http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=663&pid=1002 [题意] 给定一个有向 ...

  9. hdu 4034 Graph

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4034 题目分类:图论 题意:n个顶点,然后给出从i到j的最短路径长度,求至少需要哪些边 第二组样例 第 ...

随机推荐

  1. 如何将sqlserver表中的数据导出sql语句或生成insert into语句 [转]

    输入表名,生成插入语句 drop proc proc_insert //如果存在就删除 go create proc proc_insert (@tablename varchar(256)) as ...

  2. leetcode先刷_Unique Binary Search Trees II

    可能没想到,人的简单方法,关于质询的问题提出做. 如何把产生出来的所有的树木?所使用的方法当然是递归,但是有一个致命的问题,假设根节点,然后做一个递归,所以这是非常多的公共树木的根,结果肯定是一团糟. ...

  3. MVC模型部分验证

    ASP.NET MVC模型部分验证 在很多情况下,我们为了代码的复用可能会存在ViewModel共用的情形.比方说,web应用中常常会遇到的一个需求就是用户找回密码的功能.用户首先要验证通过验证邮箱( ...

  4. BZOJ 1208 HNOI2004 宠物收容所 平衡树/set

    标题效果:有一个宠物收容所.目前还没有被采纳的宠物或谁想要领养宠物,每个宠物有个性值,大家谁想要领养宠物具有理想人格值.每一刻,宠物收容所只是为了有谁想要领养宠物或宠物的人. 当领走宠物,将有一定程度 ...

  5. Installshield停止操作系统进程的代码--IS5版本适用

    原文:Installshield停止操作系统进程的代码--IS5版本适用 出处:http://www.installsite.org/pages/en/isp_ext.htm这个地址上有不少好东西,有 ...

  6. C#验证IP地址

    using System.Net; try { IPAddress a = IPAddress.Parse(输入的IP字符串); } catch (System.Exception ex) { Mes ...

  7. Sql Server 存储过程中查询数据无法使用 Union(All)

    原文:Sql Server 存储过程中查询数据无法使用 Union(All) 微软Sql Server数据库中,书写存储过程时,关于查询数据,无法使用Union(All)关联多个查询. 1.先看一段正 ...

  8. 快速构建Windows 8风格应用21-构建简单媒体播放器

    原文:快速构建Windows 8风格应用21-构建简单媒体播放器 本篇博文主要介绍如何构建一个简单的媒体播放器. <快速构建Windows 8风格应用20-MediaElement>博文中 ...

  9. solr主从复制

    solr主从复制 最近的开发工作涉及到两个模块“任务”和“日周报”.关系是日周报消费任务,因为用户在写日周报的时候,需要按一定的规则筛选当前用户的任务,作为日周报的一部分提交.整个项目采用类似于Orc ...

  10. 如何给TableLayout加边框

    呵呵,其实很简单 就是将TableLayout定义一种颜色,在给TableRow定义一种颜色.通过TableRow的layout_margin挤出一个像素的宽度就变成了TableLayout的宽度.这 ...