1 3 2 1 2 1 3 6 0 1 15 0 3 4 1 1 1 3 0 2 33 1 2
4 15 15
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define maxn 100005
#define MAXN 300005
using namespace std;
int n,m,ans,cnt,tot;
int head[maxn],dug[maxn];
int sum[maxn],w[maxn];
struct node
{
int u,v,num;
} edge[MAXN];
struct Node
{
int v,next,num,last;
} g[MAXN];
void addedge(int u,int v,int num)
{
cnt++;
g[cnt].v=v;
g[cnt].num=num;
g[cnt].next=head[u];
head[u]=cnt;
}
bool cmp(node xx,node yy)
{
if(xx.u!=yy.u) return xx.u<yy.u ;
if(xx.v!=yy.v) return xx.v<yy.v;
}
int main()
{
int i,j,t,u,v;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++) dug[i]=head[i]=w[i]=sum[i]=0;
for(i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);
if(u>v) swap(u,v);
edge[i].u=u;
edge[i].v=v;
edge[i].num=1;
}
sort(edge+1,edge+m+1,cmp);
tot=1;
for(i=2; i<=m; i++) // 合并相同边
{
if(edge[i].u==edge[tot].u&&edge[i].v==edge[tot].v) edge[tot].num++;
else edge[++tot]=edge[i];
}
for(i=1; i<=tot; i++) // 计算度数
{
dug[edge[i].u]++; dug[edge[i].v]++;
}
cnt=0;
for(i=1; i<=tot; i++) // 点与相邻节点度数较大的点建图
{
u=edge[i].u;
v=edge[i].v;
if(dug[v]>dug[u]) addedge(u,v,edge[i].num);
else addedge(v,u,edge[i].num);
}
int q,op,val;
scanf("%d",&q);
while(q--)
{
scanf("%d",&op);
if(op==0)
{
scanf("%d%d",&u,&val);
w[u]+=val;
for(i=head[u]; i; i=g[i].next) // 更新大点的sum值
{
v=g[i].v;
sum[v]+=g[i].num*val;
}
}
else
{
scanf("%d",&u);
ans=sum[u];
for(i=head[u]; i; i=g[i].next) // 计算未更新的大点的值
{
v=g[i].v;
if(g[i].last!=w[v])
{
ans+=g[i].num*(w[v]-g[i].last);
g[i].last=w[v];
}
}
sum[u]=ans;
printf("%d\n",ans);
}
}
}
return 0;
}
hdu 4858 项目管理 (图的分治),布布扣,bubuko.com
原文:http://blog.csdn.net/tobewhatyouwanttobe/article/details/37999129