您的位置:首页 > 编程语言 > Go语言

ZOJ3742Bellywhite's Algorithm Homework

2015-08-11 10:34 495 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3742

  给定n个点m条边的无向图,支持两个操作:

    C x:将与x相邻的边符号取反。

    Q x:

      如果x为'+',输出正边权和。

      如果x为'-',输出负边权和。

      如果x为'A',输出总边权和。

  按度数分块,将度数≥√m的点记为重点,否则为轻点。

  对于重点,我们记录positive_sum和negative_sum,代表相邻的轻-重边正、负边权和。并且记录与之相邻的重点。

  进行修改操作的时候:

    对于重点的取反,我们打上opp标记,修改时取反并更新一下即可。注意重-重边要单独修改。

    对于轻点的取反,我们暴力修改,注意轻-重边的实际边权是opp*边权即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long int64;
typedef unsigned int uint;
const int maxn=50015,maxm=100015;
int n,m,q;
vector<int> w[maxn];
bool heavy[maxn],opp[maxn];
int64 res_p,res_n,sum_p[maxn],sum_n[maxn];
int tot,deg[maxn],now[maxn],pre[maxm],son[maxm],val[maxm];
void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;}
void initial(){
res_p=res_n=0;tot=1;
memset(opp,0,sizeof(opp));
memset(now,0,sizeof(now));
memset(deg,0,sizeof(deg));
memset(heavy,0,sizeof(heavy));
memset(sum_p,0,sizeof(sum_p));
memset(sum_n,0,sizeof(sum_n));
for (int i=1;i<=n;++i) w[i].clear();
}
void init(int cases){
initial();
if (scanf("%d%d%d",&n,&m,&q)==EOF) exit(0);
if (cases>1) printf("\n");
for (int x,y,v,i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&v);
connect(x,y,v);connect(y,x,v);
(v>0?res_p:res_n)+=v;++deg[x];++deg[y];
}
for (int lim=sqrt(m),i=1;i<=n;++i) heavy[i]=(deg[i]>lim);
for (int i=1;i<=n;++i)
for (int p=now[i];p;p=pre[p])
if (heavy[i]&&heavy[son[p]]) w[i].push_back(p);
else (val[p]>0?sum_p[i]:sum_n[i])+=val[p];
}
void query(){
char op[5];scanf("%s",op);
switch (op[0]){
case 'A':printf("%lld\n",res_p+res_n);break;
case '-':printf("%lld\n",res_n);break;
case '+':printf("%lld\n",res_p);break;
}
}
void opposite(int p){
(val[p]>0?res_p:res_n)-=val[p];
val[p]=val[p^1]=-val[p];
(val[p]>0?res_p:res_n)+=val[p];
}
void modify_heavy(int u){
opp[u]^=1;
res_p-=sum_p[u];res_n-=sum_n[u];
swap(sum_p[u],sum_n[u]);sum_p[u]=-sum_p[u];sum_n[u]=-sum_n[u];
res_p+=sum_p[u];res_n+=sum_n[u];
for (uint i=0;i<w[u].size();++i) opposite(w[u][i]);
}
void modify_light(int u){
for (int p=now[u];p;p=pre[p]){
if (heavy[son[p]]){
int op=opp[son[p]]?-1:1;
if (op*val[p]>0){
res_p-=op*val[p];res_n+=op*-val[p];
sum_p[son[p]]-=op*val[p];sum_n[son[p]]+=op*-val[p];
}
else{
res_n-=op*val[p];res_p+=op*-val[p];
sum_n[son[p]]-=op*val[p];sum_p[son[p]]+=op*-val[p];
}
val[p]=val[p^1]=-val[p];
}
else opposite(p);
}
}
void modify(){
int x;scanf("%d",&x);
if (heavy[x]) modify_heavy(x);
else modify_light(x);
}
void work(){
for (int i=1;i<=q;++i){
char op[5];scanf("%s",op);
switch (op[0]){
case 'Q':query();break;
case 'C':modify();break;
}
}
}
int cases;
int main(){
while (1){init(++cases);work();}
return 0;
}


my code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: