题目链接 HDU 6251

题意 给出一个$N$个点$N$条边的无向图。然后给出$M$个操作,每个操作为$(x, y, z)$,表示把连接

$x$和$y$的边的颜色改成$z$。

求这张无向图中所有边的颜色的连通块数量。

首先不难得到这是一个环套树的结构。

首先考虑一棵树的情形。

设$f[i]$为$i$这个结点的所有边中的不同颜色数目。

那么整棵树的所有边的颜色的连通块数量即为$∑f(i) - (n - 1)$

现在把这个结论推广到环套树上。

设$f[i]$为$i$这个结点的所有边中的不同颜色数目。

那么整个图的所有边的颜色的连通块数量即为$∑f(i) - n$

但是有一种特殊情况,若这个环上所有的边的颜色相同,

那么整个图的所有边的颜色的连通块数量为$∑f(i) - (n - 1)$

#include <bits/stdc++.h>

using namespace std;

#define	rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef pair <int, int> PII; const int N = 2e5 + 10; unordered_map <int, int> mp[N], cp;
map <PII, int> mp2;
map <PII, int> oncircle; vector <int> v[N];
int T;
int n, m, cnt;
int isroot[N];
int a[N], vis[N];
int father[N];
int f[N];
int ans;
int cir;
int ca = 0; int getcircle(int x){
vis[x] = 1;
for (auto u : v[x]){
if (u == father[x]) continue;
father[u] = x;
if (vis[u]){
cnt = 0;
int w = x;
while (w ^ u){
a[++cnt] = w;
isroot[w] = cnt;
w = father[w];
} a[++cnt] = u;
isroot[u] = cnt;
return 1;
} if (getcircle(u)) return 1;
} return 0;
} int main(){ scanf("%d", &T);
while (T--){
printf("Case #%d:\n", ++ca);
scanf("%d%d", &n, &m);
rep(i, 0, n + 1) v[i].clear();
rep(i, 0, n + 1) mp[i].clear();
mp2.clear();
oncircle.clear();
cp.clear();
cnt = 0;
rep(i, 0, n + 1) a[i] = 0;
rep(i, 0, n + 1) f[i] = 0;
ans = 0;
cir = 0;
rep(i, 1, n){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if (x > y) swap(x, y);
v[x].push_back(y);
v[y].push_back(x);
if (mp[x][z] == 0){
++f[x];
++mp[x][z];
} else ++mp[x][z];
if (mp[y][z] == 0){
++f[y];
++mp[y][z];
} else ++mp[y][z];
mp2[MP(x, y)] = z;
} rep(i, 1, n) ans += f[i]; rep(i, 0, n + 1) vis[i] = 0;
getcircle(1); a[++cnt] = a[1];
rep(i, 1, cnt - 1){
int x = a[i], y = a[i + 1];
if (x > y) swap(x, y);
oncircle[MP(x, y)] = 1;
} for (auto u : oncircle){
int tt = mp2[MP(u.fi.fi, u.fi.se)];
if (cp[tt] == 0){
++cir;
++cp[tt];
} else ++cp[tt];
} while (m--){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if (x > y) swap(x, y);
int old = mp2[MP(x, y)];
--mp[x][old];
if (mp[x][old] == 0) --f[x], --ans;
--mp[y][old];
if (mp[y][old] == 0) --f[y], --ans; if (oncircle.count(MP(x, y)) > 0){
--cp[old];
if (cp[old] == 0) --cir;
} mp2[MP(x, y)] = z;
if (mp[x][z] == 0){
++mp[x][z];
++f[x];
++ans;
} else ++mp[x][z]; if (mp[y][z] == 0){
++mp[y][z];
++f[y];
++ans;
} else ++mp[y][z]; if (oncircle.count(MP(x, y)) > 0){
if (cp[z] == 0){
++cp[z];
++cir;
} else ++cp[z];
} if (cir == 1) printf("%d\n", ans - n + 1);
else printf("%d\n", ans - n);
}
} return 0;
}

HDU 6251 Inkopolis(2017 CCPC-Final,I题,环套树 + 结论)的更多相关文章

  1. HDU 6268 Master of Subgraph (2017 CCPC 杭州 E题,树分治 + 树上背包)

    题目链接  2017 CCPC Hangzhou  Problem E 题意  给定一棵树,每个点有一个权值,现在我们可以选一些连通的点,并且把这点选出来的点的权值相加,得到一个和. 求$[1, m] ...

  2. HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)

    题目链接  2017 CCPC Hangzhou Problem H 思路:对树进行分块.把第一棵树分成$\sqrt{n}$块,第二棵树也分成$\sqrt{n}$块.    分块的时候满足每个块是一个 ...

  3. 2017 ccpc哈尔滨 A题 Palindrome

    2017 ccpc哈尔滨 A题 Palindrome 题意: 给一个串\(T\),计算存在多少子串S满足\(S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)\) 思路: 很明显这里的回文串长 ...

  4. 2017 CCPC秦皇岛 A题 A Ballon Robot

    The 2017 China Collegiate Programming Contest Qinhuangdao Site is coming! There will be  teams parti ...

  5. 2017 CCPC秦皇岛 E题 String of CCPC

    BaoBao has just found a string  of length  consisting of 'C' and 'P' in his pocket. As a big fan of ...

  6. 2017 CCPC秦皇岛 M题 Safest Buildings

    PUBG is a multiplayer online battle royale video game. In the game, up to one hundred players parach ...

  7. 2017 CCPC秦皇岛 L题 One Dimensions Dave

    BaoBao is trapped in a one-dimensional maze consisting of  grids arranged in a row! The grids are nu ...

  8. 2017 CCPC秦皇岛 H题 Prime set

    Given an array of  integers , we say a set  is a prime set of the given array, if  and  is prime. Ba ...

  9. 2017 CCPC秦皇岛 G题 Numbers

    DreamGrid has a nonnegative integer . He would like to divide  into nonnegative integers  and minimi ...

随机推荐

  1. 笔记-python-反射

    笔记-python-反射 1. 反射 在很多地方看到自省和反射,很晕菜,整理了一下相关文档,加深了理解. 自省和反射其实说的是一件事,核心操作是根据输入去对象(模块)中调用(查找/获取/删除/添加)成 ...

  2. 笔记-算法-hash以及hashlib使用

    算法-hash和hash表以及hashlib使用 1.      简介 1.1.    hash Hash(散列/哈希),就是把任意长度的输入(预映射pre-image)通过散列算法变换成固定长度的输 ...

  3. couchbase map reduce

    map function(){emit(null,2);} reduce function(key, values, rereduce){ var response = {"a": ...

  4. [19/02/23]ToolsShare 工具分享 VPNTethering Android (Root Required)

    To be short, VPN Tethering is a quite useful tool when you want to share your private network with s ...

  5. LeetCode with Python -> Linked List

    21. Merge Two Sorted Lists Merge two sorted linked lists and return it as a new list. The new list s ...

  6. 【转】Unity3D 场景切换与持久化简单数据储存(PlayerPrefs类)

    本篇文章主要介绍了"Unity3D 场景切换与持久化简单数据储存(PlayerPrefs类)",主要涉及到Unity3D 场景切换与持久化简单数据储存(PlayerPrefs类)方 ...

  7. 【转】超简单利用UGUI制作圆形小地图

    http://sanwen.net/a/ithhtbo.html 由于UI都是Achor自己用PS做的,比较粗糙,大家见谅,不过丝毫不影响功能的实现,下面我们看看今天的笔记: 首先我们看看需要哪些组件 ...

  8. 【转】网页游戏能用PHP做后端开发吗? PHP Libevent扩展安装及应用

    网页游戏能用PHP做后端开发吗? 当然可以.最好走HTTP,也可以做网络编程,而且写代码超简单,1个函数就可以建一个服务器端.stream_socket_server()多线程不是什么好主意,你可以用 ...

  9. ORA-12012: 自动执行作业 "SYS"."ORA$AT_OS_OPT_SY_21" 出错

    oracle 12.2.0.1版本报错: Errors in file /u01/app/oracle/diag/rdbms/easdb/easdb2/trace/easdb2_j000_27520. ...

  10. Python 字典值相加

    #字典值相加 def union_dic(*objs): _keys = set(sum([obj.keys() for obj in objs],[])) _total = {} for _key ...