传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6251
题意:有一个n个点的图,有n条边(基环树),每条边有一种颜色,现在有m次操作(前后有影响),每次操作后求出当前的Region数(同一个Region是连通的且颜色一样)。
思路:采用map记录每一个节点所连边的颜色数,再通过dfs求出环,并记录哪些边在环上,以及用map来统计环上的颜色。通过每个节点所连边的颜色数以及环上颜色数来求出初始Region数cnt(不要用搜索求,tle到死!!)。每次更新的时候判断是否在环上,如果不在直接根据两边节点情况判断来更新cnt,如果在环上还要根据环上的颜色来更新cnt。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
vector<int>g[maxn];
typedef pair<int,int> P;
map<P,int>mpc,vis,mploop;
map<int,int>mppc[maxn],lpmp;
int cnt = 0;
bool vs[maxn];
int keyp;
int dfs2(int now,int fa)
{
if(vs[now])
{
P pp;
pp.first = min(now,fa);
pp.second = max(now,fa);
mploop[pp] = 1;
lpmp[mpc[pp]]++;
keyp = now;
return 1;
}
vs[now] = 1;
for(int i = 0;i<g[now].size();i++)
{
if(g[now][i] == fa)continue;
int tp = dfs2(g[now][i],now);
if(tp == 1)
{
P pp;
pp.first = min(now,fa);
pp.second = max(now,fa);
mploop[pp] = 1;
lpmp[mpc[pp]]++;
if(keyp == fa)
{
return -1;
}
else
return 1;
}
else if(tp == -1)return -1;
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
int n,m;
int cas = 0;
while(t--)
{
cnt = 0;
map<P,int>::iterator it;
scanf("%d%d",&n,&m);
for(int i =0;i<=n;i++)
{
g[i].clear();
mppc[i].clear();
}
mpc.clear();mploop.clear();vis.clear();lpmp.clear();
int x,y,c;
P p;
for(int i = 0;i<n;i++)
{
scanf("%d%d%d",&x,&y,&c);
g[x].push_back(y);
g[y].push_back(x);
p.first = min(x,y);
p.second = max(x,y);
mpc[p] = c; //每条边对应颜色
}
memset(vs,0,sizeof(vs));
dfs2(1,-1);
//每个点所连的颜色数
for(int i = 1;i<=n;i++)
{
for(int j = 0;j<g[i].size();j++)
{
p.first = min(i,g[i][j]);
p.second = max(i,g[i][j]);
mppc[i][mpc[p]]++;
}
cnt += mppc[i].size() - 1;
}
if(lpmp.size()==1)cnt ++ ;
printf("Case #%d:\n",++cas);
while(m--)
{
scanf("%d%d%d",&x,&y,&c);
p.first = min(x,y);
p.second = max(x,y);
if(mpc[p] == c)
{
printf("%d\n",cnt);
continue;
}
int rigc = mpc[p];
//not in circle
if(!mploop[p])
{
if(mppc[x][c]==0)
{
if(mppc[x][rigc] > 1)
cnt++;
}
else
{
if(mppc[x][rigc] == 1)
cnt --;
}
if(mppc[y][c]==0)
{
if(mppc[y][rigc] > 1)
cnt++;
}
else
{
if(mppc[y][rigc] == 1)
cnt --;
}
}
//in circle
else
{
if(lpmp.size()==1)
{
cnt++;
}
else if(lpmp.size()==2 && lpmp[rigc] == 1)
{
if(lpmp[c])
{
cnt --;
}
}
else
{
if(mppc[x][c]==0)
{
if(mppc[x][rigc] > 1)
cnt++;
}
else
{
if(mppc[x][rigc] == 1)
cnt --;
}
if(mppc[y][c]==0)
{
if(mppc[y][rigc] > 1)
cnt++;
}
else
{
if(mppc[y][rigc] == 1)
cnt --;
}
}
lpmp[rigc]--;
lpmp[c]++;
}
printf("%d\n",cnt);
mppc[x][c]++;
mppc[x][rigc]--;
mppc[y][c]++;
mppc[y][rigc]--;
mpc[p] = c;
}
}
}