hdu 4467 Graph
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的更多相关文章
- 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 ...
- [la P5031&hdu P3726] Graph and Queries
[la P5031&hdu P3726] Graph and Queries Time Limit: 10000/5000 MS (Java/Others) Memory Limit: ...
- HDU 3726 Graph and Queries treap树
题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...
- Graph HDU - 4467
https://vjudge.net/problem/HDU-4467 大概就是,设一个块大小T 对于度数<=T的点,设为1类点,在改变颜色的时候暴力查询与其相邻点,更新答案 对于度数>T ...
- HDU 4467 分块
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: ...
- HDU 4034 Graph(Floyd变形——逆向判断)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4034 Problem Description Everyone knows how to calcu ...
- hdu 4034 Graph (floyd的深入理解)
Graph Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)Total Submi ...
- HDU 5607 graph(DP+矩阵乘法)
[题目链接] http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=663&pid=1002 [题意] 给定一个有向 ...
- hdu 4034 Graph
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4034 题目分类:图论 题意:n个顶点,然后给出从i到j的最短路径长度,求至少需要哪些边 第二组样例 第 ...
随机推荐
- SSH深度历险记(两) Jboss+EJB一审
学习感悟:每次学习新知识.通过初审会从小事做起,获得成就感.经典Hello Workd我们成功的例子奠定了门哈,呢.非常好的理解了.Ejb的核心. 今天主要以这个小实例,来学习EJB的分布式,我们能够 ...
- C# .NET ASP.NET 其中关系你了解多少
有些人一直在做这方面..但突然有人来问你这些问题..估计有很多答不上来. 1..NET是一个平台,一个抽象的平台的概念. .NET平台其本身实现的方式其实还是库,抽象层面上来看是一个平台. 个人理解. ...
- Highcharts图表导出为pdf的JavaWeb实践
写给读者的话^_^: 众所周知,基于Highcharts插件生成的svg图片组(注意这里鄙人指的组是若干图有序组合,并非一张图片,具有业务意义)导出为PDF文档是有难度滴.鄙人也曾“异想天开”用前端技 ...
- leetcode先刷_Unique Binary Search Trees II
可能没想到,人的简单方法,关于质询的问题提出做. 如何把产生出来的所有的树木?所使用的方法当然是递归,但是有一个致命的问题,假设根节点,然后做一个递归,所以这是非常多的公共树木的根,结果肯定是一团糟. ...
- ShellExecute函数简单说明
平时在delphi写代码的过程中总是能遇到ShellExecute函数,于是索性将它的使用方法整理一下,由于我在微软的站点上也没能查到个详解(当然我查的中文版,俺菜嘛) ShellExecute函数原 ...
- Java获取系统相关信息System.getProperty()
java.version Java 运行时环境版本 java.vendor Java 运行时环境供应商 java.vendor.url Java 供应商的 URL java.home Java 安装目 ...
- C# 根据年、月、周、星期获得日期等
原文:C# 根据年.月.周.星期获得日期等 /// 取得某月的第一天 /// </summary> /// <param name="datetime">要 ...
- Invent 2014回顾
AWS re:Invent 2014回顾 亚马逊在2014年11月11-14日的拉斯维加斯举行了一年一度的re:Invent大会.在今年的大会上,亚马逊一股脑发布和更新了很多服务.现在就由我来带领 ...
- 系统预定义委托与Lambda表达式
NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式 开篇:在上一篇中,我们了解了匿名类.匿名方法与扩展方法等所谓的新语法,这一篇我们继续征程,看看系统预定义委托(Action/Fun ...
- Java集合之LinkedHashSet源码分析
1.简介 我们知道Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.根据源码实现中的注释我们可以知道LinkedHashSet是具有可预知迭代顺序的Set接 ...