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. POJ 2318--TOYS(二分找点,叉积判断方向)

    TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17974   Accepted: 8539 Description ...

  2. Django模板简介

    在settings.py中有个TEMPLATES的设置,其中BACKEND用来配置Django模板引擎, DIRS 定义了一个目录列表,模板引擎按列表顺序搜索这些目录以查找模板源文件 一般我们都会把模 ...

  3. BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机)

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2816  Solved: 1246[Submit][Status][Discuss] Descript ...

  4. CSS基础全荟

    一.CSS概述 1.css是什么?? 层叠样式表 2.css的引入方式 1.行内样式   在标签上加属性style="属性名1:属性值1;属性名2:属性值2;..." 2.内嵌式  ...

  5. 使用百度定位Api获取当前用户登录地址

    最近在做一个商城项目,客户想把网站做成类似于美团的效果,切换地区时,内容也跟随变化.这就要首先解决根据用户id获得地址的问题,最终决定使用百度定位(不适用于搭建反向代理的项目) String url ...

  6. 用bootstrap框架弄的网站。(首页)

    网站的每一处代码都加上注解,以便浏览! 效果图: <!doctype html>   <html lang="zh-cn">   <head> ...

  7. node、npm安装教程

    描述: Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. Node.js 的使用包 ...

  8. STM32F4使用FPU+DSP库进行FFT运算的测试过程二

    原文地址:http://www.cnblogs.com/NickQ/p/8541156.html 测试环境:单片机:STM32F407ZGT6 IDE:Keil5.20.0.0 固件库版本:STM32 ...

  9. libpng的使用

    zlib 适用于数据压缩的函式库,由Jean-loup Gailly (负责compression)和 Mark Adler (负责decompression)开发. zlib被设计成一个免费的.通用 ...

  10. Python入门学习笔记4:他人的博客及他人的学习思路

    看其他人的学习笔记,可以保证自己不走弯路.并且一举两得,即学知识又学方法! 廖雪峰:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958 ...