小冰是个八卦的人,最近她对一个社交网站很感兴趣。
由于小冰是个机器人,所以当然可以很快地弄清楚这个社交网站中用户的信息啦。
她发现这个社交网站中有N个用户,用户和用户之间可以进行互动。小冰根据用户之间互动的次数和内容判断每对用户之间的亲密度。亲密度非负,若大于零表示这两个用户之间是好友关系。由于这个网站是活跃的,所以小冰会不停地更新用户之间的亲密度。
由于隐私保护,小冰无法知道每个用户的确切性别,但是作为一只很聪明的人工智能,小冰可以通过每个用户的行为来猜测性别。当然这种猜测是不准确的,小冰有可能会改变对一个用户的判断。
小冰想知道这个社交网络的八卦度是多少。八卦度的定义是社交网络中所有异性好友之间的亲密度之和。你能帮助她吗?
输入
第一行一个整数T,表示数据组数。接下来是T组数据,每组数据的格式如下:
第一行是三个整数N, M, Q,分别表示用户数、初始的好友对数、操作数。
第二行是N个空格隔开的数,第i个数表示i号用户的性别,用0或1表示。
接下来的M行,每行三个数x, y, z,代表初始状态用户x和用户y之间的亲密度是z。除此之外的用户之间的亲密度初始为0。
接下来是Q行,每行是以下三种操作中的一种:
1. “1 x”:改变用户x的性别
2. “2 x y z”:改变用户x与用户y之间的亲密度为z
3. “3”:询问八卦度
输出
对于每组数据首先输出一行"Case #X:",X为测试数据编号。
接下来对于每一个询问,输出一行包含询问的八卦度。
数据范围
1 ≤ T ≤ 20
1 ≤ x, y ≤ N
0 ≤ z ≤ 100000
小数据
1 ≤ N, M ≤ 100
1 ≤ Q ≤ 1000
大数据
1 ≤ N, M, Q ≤ 100000
1 3 2 8 0 1 0 1 2 1 1 3 1 3 1 1 1 2 3 2 2 3 2 3 1 2 3
Case #1: 1 2 2 3
http://hihocoder.com/problemset/problem/1161?sid=413912
<pre name="code" class="cpp">#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define ll long long
using namespace std;
int sex[100001];
struct node{
int to,w;
};
vector<node> y[100001];
int main(){
int t;
scanf("%d",&t);
int cnt=0;
while(t--){
int n,m,k,a,b,c;
scanf("%d %d %d",&n,&m,&k);
for(int i=0;i<n;++i){
scanf("%d",&sex[i]);
y[i].clear();
}
ll s=0; //必须longlong
while(m--){
scanf("%d %d %d",&a,&b,&c);
a--;b--;
node tmp;
tmp.to=b; tmp.w=c;
y[a].push_back(tmp);
tmp.to=a;
y[b].push_back(tmp); //建图
if(sex[a]!=sex[b])
s+=c;
}
printf("Case #%d:\n", ++cnt);
while(k--){
scanf("%d",&a);
if(a==1){
scanf("%d",&b);
b--;
sex[b]=1-sex[b]; //修改性别
for(int i=0;i<y[b].size();++i){
if(sex[y[b][i].to]!=sex[b]) //只需改变和b连接的那部分值
s+=y[b][i].w;
else
s-=y[b][i].w;
}
}
else if(a==2){
scanf("%d %d %d",&a,&b,&c); //改变用户a与用户b之间的亲密度为c
a--;b--;
int original=0;
int u=0;
for(int i=0;i<y[a].size();++i){
if(y[a][i].to==b){
u=1;
original=y[a][i].w; //保存一份原来的值
y[a][i].w=c; //改变亲密度
break;
}
}
for(int i=0;i<y[b].size();++i){
if(y[b][i].to==a){
y[b][i].w=c;
break;
}
}
if(u==0){ //注意!!如果ab没有出现过,则应新增一条ab的边
node tmp; tmp.to=b; tmp.w=c;
y[a].push_back(tmp);
tmp.to=a;
y[b].push_back(tmp);
}
if(sex[a]!=sex[b])
s+=c-original; //只修改当前边的值
}
else
printf("%lld\n",s);
}
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100005
int c,T,n,m,q;
int s[N],first[N],top;
struct edge{
int y,next,w;
}e[N<<5];
long long res;
void add(int x,int y,int w){
e[top].y = y;
e[top].w = w;
e[top].next = first[x];
first[x] = top++;
}
void update(int x){
int i,y;
for(i = first[x];i!=-1;i=e[i].next){
y = e[i].y;
if(s[x] == s[y])
res -= e[i].w;
else
res += e[i].w;
}
}
int change(int x,int y,int w){
int i,tmp = -1;
for(i = first[x];i!=-1;i=e[i].next){
if(e[i].y == y){
tmp = e[i].w;
e[i].w = w;
return tmp;
}
}
add(x,y,w);
return 0;
}
int main(){
scanf("%d",&T);
for(c = 1;c<=T;c++){
int i,j,a,b,w,op;
res = 0;
memset(first, -1, sizeof(first));
top = 0;
scanf("%d %d %d",&n,&m,&q);
for(i = 1;i<=n;i++)
scanf("%d",&s[i]);
for(i = 1;i<=m;i++){
scanf("%d %d %d",&a,&b,&w);
add(a,b,w);
add(b,a,w);
if(s[a] != s[b])
res += w;
}
printf("Case #%d:\n",c);
while(q--){
scanf("%d",&op);
if(op == 1){
scanf("%d",&a);
s[a] = 1-s[a];
update(a);
}else if(op == 2){
scanf("%d %d %d",&a,&b,&w);
j = change(a,b,w);
change(b,a,w);
if(s[a] != s[b]){
res -= j;
res += w;
}
}else
printf("%lld\n",res);
}
}
return 0;
}
vector可以等价的写成这样(减少时间,甚至比vector更好用):
int first[...];
struct edge{
int y,next,w;
}e[...];
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
for(i = first[x];i!=-1;i=e[i].next)
dfs(e[i].y);