BZOJ 4238 电压 解题报告

BZOJ 4238 电压

考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环

则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上。

考虑建出dfs树,那么返祖边一定在环上。

把边下放到点上,考虑处理出返祖边覆盖的两个端点直接的路径,这些点都在这个环上,按照这个环的奇偶打一个差分上去即可。

但是这样只考虑了只有一个返祖边在环上的情况,返祖边在两个环以上的环我们没有处理

考虑分类讨论

  • 若两个有交返祖边奇偶不同,少处理的一个环是奇环,无论是大奇环还是小奇环都没有影响
  • 若均为奇环,那么奇环的交不在大偶环上,也没有影响
  • 若均为偶环,显然都不会成为答案

但是我们还需要考虑非树边

如果仅有一个奇环,那么奇环上的边都是答案

否则两个有交的非树边奇环一定构成了一个大偶环,使非树边不成为答案。


Code:

#include <cstdio>
#include <cctype>
#include <map>
#include <algorithm>
#define ll long long
using std::max;
using std::min;
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
    x=0;char c=gc();
    while(!isdigit(c)) c=gc();
    while(isdigit(c)) x=x*10+c-'0',c=gc();
}
const int N=2e5+10;
int head[N],to[N<<2],Next[N<<2],cnt=1;
void add(int u,int v)
{
    to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int n,m,dep[N],jh[N],oh[N],vis[N<<2],jhc,ohc,ans;
void dfs(int now)
{
    for(int v,i=head[now];i;i=Next[i])
    {
        if(vis[i^1]) continue;
        v=to[i];
        vis[i]=1;
        if(!dep[v])
        {
            dep[v]=dep[now]+1;
            dfs(v);
            jh[now]+=jh[v];
            oh[now]+=oh[v];
        }
        else if((dep[now]-dep[v])&1)
            ++ohc,++oh[now],--oh[v];
        else
            ++jhc,++jh[now],--jh[v];
    }
}
int main()
{
    read(n),read(m);
    for(int u,v,i=1;i<=m;i++)
    {
        read(u),read(v);
        add(u,v),add(v,u);
    }
    for(int i=1;i<=n;i++)
        if(!dep[i])
            dep[i]=1,dfs(i);
    for(int i=1;i<=n;i++)
    {
        if(dep[i]==1) continue;
        if(!jhc) ans+=oh[i]==0;
        else if(jhc==1) ans+=jh[i]&&(oh[i]==0);
        else ans+=(jh[i]==jhc)&&(oh[i]==0);
    }
    printf("%d\n",ans+(jhc==1));
    return 0;
}

2019.6.26

转载于:https://www.cnblogs.com/butterflydew/p/11090715.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值