编程之美初赛第二场 八卦的小冰(长模拟)

小冰是个八卦的人,最近她对一个社交网站很感兴趣。

由于小冰是个机器人,所以当然可以很快地弄清楚这个社交网站中用户的信息啦。

她发现这个社交网站中有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);  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值