Inkopolis
Time Limit: 24000/12000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 322 Accepted Submission(s): 80
Problem Description
Inkopolis is the city in which Inklings live in, it can be regarded as an undirected connected graph with exactly N vertices and N edges between vertices. It is guaranteed that the graph doesn’t contain duplicated edges or self loops. Inklings can splatter a special type of colored ink to decorate the roads they live in. Inklings are capricious so they often change the color of the roads to celebrate the upcoming Splatfest.
The Splatfest lasts for exactly M days, on each day Inklings will splatter ink on exactly one road, the color on this road will be coverd by the new color of the ink. At the end of each day, they wonder how many different colored regions are there in the Inkopolis. A colored region is a set of connected roads with same color, to be clear, two roads are in the same colored region if they have the same color and share a common vertex.
Input
The first line of the input gives the number of test cases, T. T test cases follow.
For each test case, the first line contains two integers N and M, where N is the number of vertexes and roads in Inkopolis, and M is the number of days that Splatfest lasts.
Following N lines describe the roads between the vertexes. Each line contains 3 integers x, y, c, representing there is a road with color c between the xth and the ythvertex.
Next following M lines describe the operations on each day. Each line contains 3 integers x, y, c, representing an operation that Inklings splatter the ink with color c to the road between the xth and the yth vertex, it is guaranteed that there is such a road.
1≤T≤100
3≤N≤2×105
1≤M≤2×105
1≤x,y,c≤n
∑N,∑M≤106
Output
For each test case, output one line containing “Case #x:” first, where x is the test case number (starting from 1).
The following M lines each consists of an integer which is the number of colored regional in Inkopolis after each day.
Sample Input
2 4 3 4 2 4 2 3 3 3 4 2 1 4 1 3 4 2 2 3 4 3 4 3 4 4 1 2 1 2 3 1 3 4 1 4 1 1 1 2 2 3 4 2 2 3 2 4 1 4
Sample Output
Case #1: 4 3 3 Case #2: 2 4 2 2
Source
2017中国大学生程序设计竞赛-总决赛-重现赛(感谢哈工大)
Recommend
liuyiding
题意:给你只有一个环的树,树上的边有颜色,每次修改一个边的颜色,每次修改后问树上有多少个颜色块。
解题思路:
题目答案就是:
f[i]表示节点i周围不同颜色数
对于树:
对于环:
如果环上只有一种颜色:
那么就是怎么维护这个f[i],和环上的颜色数了。直接上map暴力维护就好了。详见代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=200005;
typedef long long ll;
inline void scan_d(int &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0'), c = getchar();
}
}
struct edge{
int u;
int v;
int w;
int next;
}e[MAXN*2];
int edge_num,head[MAXN];
void insert_edge(int u,int v,int w){
e[edge_num].u=u;
e[edge_num].v=v;
e[edge_num].w=w;
e[edge_num].next=head[u];
head[u]=edge_num++;
}
int N,M;
map<pair<int,int>,int> G;//保存每条边的颜色
map<int,int> Col[MAXN];//保存每个点周围的颜色的数量
map<int,int> Cir;//保存环上的颜色的数量
int pre[MAXN];//用于深搜回溯
int prew[MAXN];
bool flag=0;
bool vis[MAXN];
bool tag[MAXN];//当前点是否在环上
void dfs(int u,int fa){
if(flag)
return;
vis[u]=1;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
if(v==fa)
continue;
if(vis[v]==0){
pre[v]=u;
prew[v]=e[i].w;
dfs(v,u);
}
else{
int ok=u;
tag[v]=1;
Cir[e[i].w]++;
while(ok!=v){
tag[ok]=1;
Cir[prew[ok]]++;
ok=pre[ok];
}
flag=1;
}
if(flag)
return;
}
}
int main(){
int T;
scan_d(T);
for(int ttt=1;ttt<=T;ttt++){
printf("Case #%d:\n",ttt);
scan_d(N);
scan_d(M);
flag=0;
edge_num=0;
Cir.clear();
G.clear();
for(int i=1;i<=N;i++){
Col[i].clear();
tag[i]=0;
vis[i]=0;
head[i]=-1;
}
int u,v,w;
for(int i=1;i<=N;i++){
scan_d(u);
scan_d(v);
scan_d(w);
G[make_pair(u,v)]=w;
G[make_pair(v,u)]=w;
Col[u][w]++;
Col[v][w]++;
insert_edge(u,v,w);
insert_edge(v,u,w);
}
dfs(1,1);//深搜找环
int tot=0;
int hsize=Cir.size();
for(int i=1;i<=N;i++)
tot+=Col[i].size();
tot-=N;
while(M--){
scan_d(u);
scan_d(v);
scan_d(w);
int lw=G[make_pair(u,v)];
G[make_pair(u,v)]=w;
G[make_pair(v,u)]=w;
//把之前的颜色删掉
if(--Col[u][lw]==0)
tot--;
if(--Col[v][lw]==0)
tot--;
//把新的颜色加进去
if(++Col[u][w]==1)
tot++;
if(++Col[v][w]==1)
tot++;
//环上特殊处理
if(tag[u]&&tag[v]){
if(--Cir[lw]==0)
hsize--;
if(++Cir[w]==1)
hsize++;
}
if(hsize==1)//如果环只有一种颜色
printf("%d\n",tot+1);
else
printf("%d\n",tot);
}
}
return 0;
}