题目链接 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. 定时任务之crond服务

    计划任务分为一次性计划任务与长期性计划任务 一次性计划任务:今天11:25执行重启网卡操作,执行结束 即任务消失  一次性计划任务格式: 创建:"at 时间" #默认采用的是交互式 ...

  2. vijos1083:小白逛公园

    小白逛公园 描述 小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. 一开始,小白就根据公园的 ...

  3. Linux磁盘与文件管理系统

    基本上Linux的正统文件系统为Ext2,该文件系统内的信息主要有: superblock:记录此filesystem的整体信息,包括inode/block的总量,使用量,剩余量,以及文件系统的格式与 ...

  4. 【Remove Duplicates from Sorted Array】cpp

    题目: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ Given a sorted array, remove ...

  5. leetcode 【 Subsets II 】python 实现

    题目: Given a collection of integers that might contain duplicates, S, return all possible subsets. No ...

  6. 基于单层决策树的AdaBoost算法源码

    基于单层决策树的AdaBoost算法源码 Mian.py # -*- coding: utf-8 -*- # coding: UTF-8 import numpy as np from AdaBoos ...

  7. Gym100623A Access Control Lists

    Gym 100623A Access Control Lists 这个题很sb啊,就是去设置个交换机 我们可以给一个IP进行设置,也可以对一个网段就行设置,但是IP是优于网段的,比如样例的第一个 网段 ...

  8. Spread.js 上下级关系

  9. 生成比较短的Token字符串

    有的时候,我们需要生成一些Token作为标识:如认证后的标识符,资源的提取码等.一个比较常见的算法是生成一个GUID来作为Token,由于GUID的随机性和唯一性特点,作为Token是一个非常可靠的选 ...

  10. box-sizing重置

    html { /*-webkit-box-sizing: border-box; -moz-box-sizing: border-box;*/ box-sizing: border-box; } *, ...