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的最短路径长度,求至少需要哪些边 第二组样例 第 ...
随机推荐
- C# 实现设置系统环境变量设置
原文:C# 实现设置系统环境变量设置 以前实现系统环境变量设置时是要在电脑属性--高级--环境变量设置,实现方式主要有2种, 修改注册表,添加环境变量 调用系统Kernel32.DLL函数,设置环境变 ...
- 转载:Eclipse+Spket插件+ExtJs4修改版提供代码提示功能[图]
转载:Eclipse+Spket插件+ExtJs4修改版提供代码提示功能[图] ExtJs是一种主要用于创建前端用户界面,是一个基本与后台技术无关的前端ajax框架.功能丰富,无人能出其右.无论是界面 ...
- 【转】Oracle修改表空间为自动扩展
1.数据文件自动扩展的好处1)不会出现因为没有剩余空间可以利用到数据无法写入2)尽量减少人为的维护3)可以用于重要级别不是很大的数据库中,如测试数据库等 2.数据文件自动扩展的弊端1)如果任其扩大,在 ...
- 通过Web Api 和 Angular.js 构建单页面的web 程序
通过Web Api 和 Angular.js 构建单页面的web 程序 在传统的web 应用程序中,浏览器端通过向服务器端发送请求,然后服务器端根据这个请求发送HTML到浏览器,这个响应将会影响整个的 ...
- 安卓MonkeyRunner源码分析之与Android设备通讯方式
如前文<谁动了我的截图?--Monkeyrunner takeSnapshot方法源码跟踪分析>所述,本文主要会尝试描述android的自动化测试框架MonkeyRunner究竟是如何和目 ...
- 大批量烧写openwrt系统
http://wiki.openwrt.org/toh/tp-link/tl-wr1043nd OEM mass flashing Flashing hundreds of devices using ...
- 终于有人把O2O、C2C、B2B、B2C的区别讲透了!
终于有人把O2O.C2C.B2B.B2C的区别讲透了! 一.O2O.C2C.B2B.B2C的区别在哪里? O2O是online to offline分为四种运营模式: 1.online to offl ...
- javascript 学习总结(九)面向对象编程
1.面向对象的工厂方法 function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; ...
- ASP.NET MVC+Knockout+Web API+SignalR
架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 2014-01-16 18: ...
- WCF 自承载
WCF 自承载 提供源码 一.WCF 简单介绍 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,是一套通讯接口.现在比较流行的S ...