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. JDBC jar包

    密码qiij https://pan.baidu.com/share/init?surl=oBfMwQ6rd9t6VNjIluF1qw

  2. 自己理解的数据库shcema

    不懂就被人嘲笑呀 ,你还不知道怎么说. 从定义中我们可以看出schema为数据库对象的集合,为了区分各个集合,我们需要给这个集合起个名字,这些名字就是我们在企业管理器的方案下看到的许多类似用户名的节点 ...

  3. NPM 常见错误

    找不到兼容版本 你有一个过时的npm.请更新到最新稳定的npm. 权限错误 npm ERR! code EPERM npm ERR! code EACCES 修复缓存的权限sudo chown -R ...

  4. mybatis自动生成@Table、@Column、@Id注解

    在pom.xml中添加如下插件以及插件相关的依赖 <build> <plugins> <plugin> <groupId>org.springframe ...

  5. 选课(树形DP)

    题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...

  6. poj 3259 Wormholes : spfa 双端队列优化 判负环 O(k*E)

    /** problem: http://poj.org/problem?id=3259 spfa判负环: 当有个点被松弛了n次,则这个点必定为负环中的一个点(n为点的个数) spfa双端队列优化: 维 ...

  7. 线程池的类型以及执行线程submit()和execute()的区别

    就跟题目说的一样,本篇博客,本宝宝主要介绍两个方面的内容,其一:线程池的类型及其应用场景:其二:submit和execute的区别.那么需要再次重申的是,对于概念性的东西,我一般都是从网上挑选截取,再 ...

  8. nigx配置location规则

    以下是收集的,对于不是很熟的朋友,配置转发很有帮助 1.location匹配命令和优先级: 优先级: Directives with the = prefix that match the query ...

  9. win10家庭版升级为win10专业版

    windows10 升级钥匙: DR9VN-GF3CR-RCWT2-H7TR8-82QGT 亲测可用

  10. lvs集群实现lvs-dr模型和lvs-nat模型

    ipvsadm ipvsadm命令是lvs集群在应用层的管理工具,我们可以通过此ipvsadm来管理lvs的配置,其实现了集群服务管理:增.删.改,集群服务的RS管理:增.删.改以及查看集群状态. 管 ...