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的最短路径长度,求至少需要哪些边 第二组样例 第 ...
随机推荐
- PKU 1276 Cash Machine
<span style="color:#000099;">/* Cash Machine Time Limit: 1000MS Memory Limit: 10000K ...
- 谢绝艳照门 - 手把手教你把当今很hit的家庭监控IP Camera变得网络安全起来
IP Camerars现在已经越来越便宜了,很多人都可以买得起,并且大家也乐意去购买,因为它们的确是用来监控你在高房价的中国购买的爱巢的非常便利的设备.当然,配套的监控应用也层出不穷,从通用的家庭安全 ...
- Java 实现迭代器(Iterator)模式
类图 /** * 自己定义集合接口, 相似java.util.Collection * 用于数据存储 * @author stone * */ public interface ICollection ...
- 使用oracle的exp命令时,提示出--hash: exp: command not found
使用oracle的exp命令时,提示出--hash: exp: command not found 原因:当你在终端使用exp的命名时,当前的账户,并不是oracle认可的账户. 在安装oracle时 ...
- Arcgis for JS实现台风运动路径与影像范围的显示
首先,看看详细的效果: 初始化状态 绘制中 绘制完毕 首先,组织数据.我组织的数据是JSON的,数据的详细形式例如以下: 其次,实现思路. 1.加入显示路径. 依据起始点,生成polyline的JSO ...
- SQL 中OPENQUERY的使用
原文:SQL 中OPENQUERY的使用 OpenQuery 是SQL Server用来与其他Server交互的一种技术,通过OpenQuery,SQL Server 可以直接访问其他数据库资源. 而 ...
- html5跨域数据传递(postMessage)
在html5中有个支持跨域传递的方法postMessage,可是实现iframe之间的数据传递! 代码如下:数据发送页面 <!DOCTYPE HTML> <html lang=&qu ...
- Ubuntu下开发环境搭建
安装基础开发包,主要gcc,g++等 sudo apt-get install build-essential 未完待续
- php+ajax+json
来个例子:(json.html) <html lang="en"> <head> <meta charset="UTF-8"> ...
- sql分组合并字段重复项sql for xml path
-------------------------(情景描述) 在我们处理数据时,可能会碰到这种情景: Id Name 1 a,b 2 ...