Description

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 x th 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 ≤ 10 5), where n is the number of nodes and m is the number of edges. 
The second line consists of n integers, the i th of which represents the color of the i th 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 ≤ 2 31 - 1) between u and v (u != v). 
The next line contains only one integer q (1 ≤ q ≤ 10 5), 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.
 
题目大意:给n个点m条无向边,每个点有一个颜色(0 or 1),每条边有一个权值。有q个询问,或翻转某个结点的颜色,或询问一个点的颜色为x、另一个点的颜色为y的边的权和。
思路:直接暴力复杂度高达O(qm),完全无法承受。好像没有其他方法,我们只能暴力地优美一点。
用一个sum[]记录答案,询问的时候O(1)输出。
记deg[u]为结点u的度,对于所有deg[v]<deg[u],连一条边v→u。
state[u]记录对于所有deg[v]<deg[u]的v↔u的权值和。
当修改u的时候,对于所有deg[v]<deg[u],利用state直接修改。对于deg[v]≥deg[u],一个一个修改。
对于一个无重边的图来讲,对每个点来说,所有度数大于等于它的点不超过$ O(\sqrt{m}) $个(因为若一个点的度数为$k$,那么度数大于等于它的点最多$x \leq k$个,这些点的度数总和至少是$k^2$,由于$k^2<=2 \times m$,所以$O(x)=O(\sqrt m)$)
那么时间复杂度为$O(q \times \sqrt m )$
这题要去重边(权和相加)。不去重边,2个点10W条边你还得死……
 
代码(3187MS):
 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXE = ; struct Edge {
int from, to, del;
LL w;
void read() {
scanf("%d%d%I64d", &from, &to, &w);
del = ;
if(from > to) swap(from, to);
}
bool operator < (const Edge &rhs) const {
if(from != rhs.from) return from < rhs.from;
return to < rhs.to;
}
bool operator == (const Edge &rhs) const {
return from == rhs.from && to == rhs.to;
}
} edge[MAXE]; LL sum[];
int n, m, q;
int head[MAXN], deg[MAXN], ecnt;
int col[MAXN];
LL state[MAXN][];
int to[MAXE], next[MAXE], dir[MAXE];
LL weight[MAXE]; void init() {
memset(head, , sizeof(head));
memset(sum, , sizeof(sum));
memset(deg, , sizeof(deg));
memset(state, , sizeof(state));
ecnt = ;
} void add_edge(int u, int v, LL w, bool flag) {
to[ecnt] = v; weight[ecnt] = w; dir[ecnt] = flag; next[ecnt] = head[u]; head[u] = ecnt++;
} void change() {
int x, c;
scanf("%d", &x);
c = col[x]; col[x] = !col[x];
sum[c] -= state[x][];
sum[c + ] -= state[x][];
sum[col[x]] += state[x][];
sum[col[x] + ] += state[x][];
for(int p = head[x]; p; p = next[p]) {
int &v = to[p];
if(!dir[p]) {
state[v][c] -= weight[p];
state[v][col[x]] += weight[p];
}
sum[c + col[v]] -= weight[p];
sum[col[x] + col[v]] += weight[p];
}
} char s[]; int main() {
int t = ;
while(scanf("%d%d", &n, &m) != EOF) {
init();
for(int i = ; i <= n; ++i) scanf("%d", &col[i]);
for(int i = ; i <= m; ++i) {
edge[i].read();
sum[col[edge[i].from] + col[edge[i].to]] += edge[i].w;
}
printf("Case %d:\n", ++t);
sort(edge + , edge + m + );
for(int i = ; i < m; ++i) {
if(edge[i] == edge[i + ]) {
edge[i].del = true;
edge[i + ].w += edge[i].w;
} else {
++deg[edge[i].from], ++deg[edge[i].to];
}
}
for(int i = ; i <= m; ++i) {
if(edge[i].del) continue;
if(deg[edge[i].from] < deg[edge[i].to]) {
add_edge(edge[i].from, edge[i].to, edge[i].w, );
state[edge[i].to][col[edge[i].from]] += edge[i].w;
} else if(deg[edge[i].from] > deg[edge[i].to]) {
add_edge(edge[i].to, edge[i].from, edge[i].w, );
state[edge[i].from][col[edge[i].to]] += edge[i].w;
} else {
add_edge(edge[i].from, edge[i].to, edge[i].w, );
add_edge(edge[i].to, edge[i].from, edge[i].w, );
}
}
scanf("%d", &q);
while(q--) {
scanf("%s", s);
if(*s == 'A') {
int x, y;
scanf("%d%d", &x, &y);
printf("%I64d\n", sum[x + y]);
} else change();
}
}
}

代码(3078MS)(稍微改了一下):

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXE = ; struct Edge {
int from, to, del;
LL w;
void read() {
scanf("%d%d%I64d", &from, &to, &w);
del = ;
if(from > to) swap(from, to);
}
bool operator < (const Edge &rhs) const {
if(from != rhs.from) return from < rhs.from;
return to < rhs.to;
}
bool operator == (const Edge &rhs) const {
return from == rhs.from && to == rhs.to;
}
} edge[MAXE]; LL sum[];
int n, m, q;
int head[MAXN], deg[MAXN], ecnt;
int col[MAXN];
LL state[MAXN][];
int to[MAXE], next[MAXE];
LL weight[MAXE]; void init() {
memset(head, , sizeof(head));
memset(sum, , sizeof(sum));
memset(deg, , sizeof(deg));
memset(state, , sizeof(state));
ecnt = ;
} void add_edge(int u, int v, LL w) {
to[ecnt] = v; weight[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++;
} void change() {
int x, c;
scanf("%d", &x);
c = col[x]; col[x] = !col[x];
sum[c] -= state[x][];
sum[c + ] -= state[x][];
sum[col[x]] += state[x][];
sum[col[x] + ] += state[x][];
for(int p = head[x]; p; p = next[p]) {
int &v = to[p];
state[v][c] -= weight[p];
state[v][col[x]] += weight[p];
sum[c + col[v]] -= weight[p];
sum[col[x] + col[v]] += weight[p];
}
} char s[]; int main() {
int t = ;
while(scanf("%d%d", &n, &m) != EOF) {
init();
for(int i = ; i <= n; ++i) scanf("%d", &col[i]);
for(int i = ; i <= m; ++i) {
edge[i].read();
sum[col[edge[i].from] + col[edge[i].to]] += edge[i].w;
}
printf("Case %d:\n", ++t);
sort(edge + , edge + m + );
for(int i = ; i < m; ++i) {
if(edge[i] == edge[i + ]) {
edge[i].del = true;
edge[i + ].w += edge[i].w;
} else {
++deg[edge[i].from], ++deg[edge[i].to];
}
}
for(int i = ; i <= m; ++i) {
if(edge[i].del) continue;
if(deg[edge[i].from] < deg[edge[i].to]) {
add_edge(edge[i].from, edge[i].to, edge[i].w);
state[edge[i].to][col[edge[i].from]] += edge[i].w;
} else {
add_edge(edge[i].to, edge[i].from, edge[i].w);
state[edge[i].from][col[edge[i].to]] += edge[i].w;
}
}
scanf("%d", &q);
while(q--) {
scanf("%s", s);
if(*s == 'A') {
int x, y;
scanf("%d%d", &x, &y);
printf("%I64d\n", sum[x + y]);
} else change();
}
}
}

HDU 4467 Graph(图论+暴力)(2012 Asia Chengdu Regional Contest)的更多相关文章

  1. HDU 4468 Spy(KMP+贪心)(2012 Asia Chengdu Regional Contest)

    Description “Be subtle! Be subtle! And use your spies for every kind of business. ”― Sun Tzu“A spy w ...

  2. 2012 Asia Chengdu Regional Contest

    Browsing History http://acm.hdu.edu.cn/showproblem.php?pid=4464 签到 #include<cstdio> #include&l ...

  3. HDU-4432-Sum of divisors ( 2012 Asia Tianjin Regional Contest )

    Sum of divisors Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. HDU 4436 str2int(后缀自动机)(2012 Asia Tianjin Regional Contest)

    Problem Description In this problem, you are given several strings that contain only digits from '0' ...

  5. HDU 4433 locker 2012 Asia Tianjin Regional Contest 减少国家DP

    意甲冠军:给定的长度可达1000数的顺序,图像password像锁.可以上下滑动,同时会0-9周期. 每个操作.最多三个数字连续操作.现在给出的起始序列和靶序列,获得操作的最小数量,从起始序列与靶序列 ...

  6. HDU 4115 Eliminate the Conflict(2-SAT)(2011 Asia ChengDu Regional Contest)

    Problem Description Conflicts are everywhere in the world, from the young to the elderly, from famil ...

  7. HDU 4441 Queue Sequence(优先队列+Treap树)(2012 Asia Tianjin Regional Contest)

    Problem Description There's a queue obeying the first in first out rule. Each time you can either pu ...

  8. HDU 4433 locker(DP)(2012 Asia Tianjin Regional Contest)

    Problem Description A password locker with N digits, each digit can be rotated to 0-9 circularly.You ...

  9. HDU 4431 Mahjong(枚举+模拟)(2012 Asia Tianjin Regional Contest)

    Problem Description Japanese Mahjong is a four-player game. The game needs four people to sit around ...

随机推荐

  1. tracking

    https://reid-mct.github.io/   1st Workshop on Target Re-Identification and Multi-Target Multi-Camera ...

  2. springboot2.04+mybatis-plus+swagger2+CodeGenerator

    @author zhangyh SpringBoot技术栈搭建个人博客[项目准备]  RESTful API就是一套协议来规范多种形式的前端和同一个后台的交互方式 原型设计 事实上,我是直接先去找的原 ...

  3. DB数据源配置之抽象(〇)

    DB数据源配置之抽象(〇) liuyuhang原创,未经允许禁止转载 DB数据源之SpringBoot+Mybatis踏坑过程实录(一) DB数据源之SpringBoot+MyBatis踏坑过程(二) ...

  4. JS模块化知识总结

    背景 <script src="a.js"></script> <script src="b.js"></script ...

  5. C++ string和int相互转换

    首先需要C++ 11的支持 打开devC++,点击tools,点击编译环境,然后出现的框第一个勾选,输入-std=c++11即可 然后使用 to_string() 和 atoi() 就可以轻松实现其相 ...

  6. 在Liunx Mint下无法切换到root用户

    提示 su: Authentication failure 以ubuntu的mint root用户默认是也是禁止的 需要手动打开才行 a)root启用 执行下面的操作:1.先解除root锁定,为roo ...

  7. JS数组push一个对象

    这个是正确的数据添加对象 var dypieArr = []; var dyArr = []; var arrStr = ''; for(var i = 0; i < dataStreet.le ...

  8. YII2 不通过composer安装Ueditor编辑器

    今天用composer安装Ueditor,一直下载失败,不知道为什么,所以就手动安装了一下.记录一下安装步骤 GitHub地址 https://github.com/BigKuCha/yii2-ued ...

  9. ruby File类

    类方法 路径相关: File.basename(filename <, suffix>) -> string返回给定文件名 filename 的最后一部分.如果有 suffix 参数 ...

  10. semcms 网站漏洞挖掘过程与安全修复防范

    emcms是国内第一个开源外贸的网站管理系统,目前大多数的外贸网站都是用的semcms系统,该系统兼容许多浏览器,像IE,google,360极速浏览器都能非常好的兼容,官方semcms有php版本, ...