习题:电压(LCA&树上差分)
Posted loney-s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了习题:电压(LCA&树上差分)相关的知识,希望对你有一定的参考价值。
题目
思路
首先对于对于高低电压,其实就是二染色问题
有了这个想法之后
自然就会想到图中的环的奇偶性
如何快速的判断呢?
笔者用的是建树+LCA的办法
之后,如果是奇环,环上的所有的边+1
如果是偶环,则-1
用树上差分的办法可以以 (O(1))的优秀时间复杂度处理
之后判断每一个边的值是否为奇环的总数即可
代码
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
int n,m;
int ans;
int cnt;
int depth[100005];
int c[100005];
int dp[100005][25];
int num;
map<int,bool> f[100005];
vector<int> g[100005];
vector<int> tre[100005];
bool vis[100005];
void read(int &x)
{
x=0;
char c=getchar();
int f=1;
while('0'>c||c>'9')
{
if(x=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<10)
{
putchar(x+'0');
}
else
{
write(x/10);
putchar(x%10+'0');
}
}
void dfs(int u,int fa)
{
vis[u]=1;
depth[u]=depth[fa]+1;
dp[u][0]=fa;
for(int i=1;i<=20;i++)
dp[u][i]=dp[dp[u][i-1]][i-1];
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(!vis[v])
{
tre[u].push_back(v);
dfs(v,u);
}
else
f[u][v]=1;
}
}
void solve(int u)
{
vis[u]=1;
for(int i=0;i<tre[u].size();i++)
{
int v=tre[u][i];
solve(v);
c[u]+=c[v];
}
if(c[u]==num&&dp[u][0])
ans++;
}
int lca(int u,int v)
{
if(depth[u]>depth[v])
swap(u,v);
for(int i=20;i>=0;i--)
{
if(depth[dp[v][i]]>=depth[u])
v=dp[v][i];
}
if(u==v)
return u;
for(int i=20;i>0;i--)
{
if(dp[u][i]!=dp[v][i])
{
u=dp[u][i];
v=dp[v][i];
}
if(dp[u][0]==dp[v][0])
return dp[u][0];
}
return dp[u][0];
}
int main()
{
read(n);
read(m);
for(int i=1;i<=m;i++)
{
int s,e;
read(s);
read(e);
g[s].push_back(e);
g[e].push_back(s);
}
for(int i=1;i<=n;i++)
if(!vis[i])
dfs(i,0);
for(int i=1;i<=n;i++)
{
vis[i]=0;
for(int j=0;j<g[i].size();j++)
{
if(f[i][g[i][j]]&&f[g[i][j]][i])
{
int t=lca(i,g[i][j]);
int s=depth[i]+depth[g[i][j]];
if(s%2)
{
c[t]+=2;
c[i]--;
c[g[i][j]]--;
}
else
{
c[i]++;
c[g[i][j]]++;
c[t]-=2;
num++;
}
}
}
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
solve(i);
}
}
if(num==2)
ans++;
write(ans);
return 0;
}
以上是关于习题:电压(LCA&树上差分)的主要内容,如果未能解决你的问题,请参考以下文章