• bzoj4238 电压


      首先先直接对图进行二染色,dfs染完色后,有的边为搜索树边,有的为非树边,当非树边连接的两头的点为异色的时候,那么很明显这条非树边和树边构成的环上的边必然不可能成为答案;如果非树边的两端的点同色,那么所有这种类型的非树边与树边构成的环的交集就是答案,对于一条这样的非树边,如果要使其变成二分图的合法边,那么必然会在其与树边构成的环中剔除掉一条边,这样树变成了两个部分,把其中一部分反色,在连上这条非树边,也是一个合法二分图,那么所有这种类型的边构成的环的交集,就是答案的可选集。

      代码

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #define N 500010
      5 using namespace std;
      6 int n,m,i,a[N],b[N],dp,p[N],pre[N],tt[N],id[N],vis[N],treeEdge[N];
      7 int deep[N],color[N],fa[N],sum[N],cnt,value[N];
      8 int s[N][21];
      9 void link(int x,int y,int z)
     10 {
     11     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;id[dp]=z;
     12 }
     13 void dfs(int x)
     14 {
     15     int i;
     16     vis[x]=1;
     17     i=p[x];
     18     while (i)
     19     {
     20         if (!vis[tt[i]])
     21         {
     22             deep[tt[i]]=deep[x]+1;
     23             treeEdge[id[i]]=1;
     24             color[tt[i]]=1-color[x];
     25             fa[tt[i]]=x;
     26             dfs(tt[i]);
     27         }    
     28         i=pre[i];    
     29     }
     30 }
     31 void gao(int x)
     32 {
     33     int i,tmp=0;
     34     vis[x]=1;
     35     i=p[x];
     36     while (i)
     37     {
     38         if (!vis[tt[i]])
     39         {
     40             gao(tt[i]);
     41             tmp+=sum[tt[i]];
     42             value[id[i]]=sum[tt[i]];
     43         }
     44         i=pre[i];
     45     }
     46     sum[x]+=tmp;
     47 }
     48 int lca(int x,int y)
     49 {
     50     if(deep[x]>deep[y])x^=y^=x^=y;
     51     int i;
     52     for(i=19;i>=0;i--)
     53     {
     54         if(deep[y]-deep[x]>=(1<<i))
     55         {
     56             y=s[y][i];
     57         }
     58     }
     59     if(x==y)return x;
     60     for(i=19;i>=0;i--)
     61     {
     62         if(s[x][i]!=s[y][i])
     63         {
     64             x=s[x][i];
     65             y=s[y][i];
     66         }
     67     }
     68     return fa[x];
     69 }
     70 
     71 int main()
     72 {
     73     scanf("%d%d",&n,&m);
     74     for (i=1;i<=m;i++)
     75     {
     76         scanf("%d%d",&a[i],&b[i]);
     77         link(a[i],b[i],i);
     78         link(b[i],a[i],i);
     79     }
     80     for (i=1;i<=n;i++) if (!vis[i]) dfs(i);
     81     for(i=1;i<=n;i++)s[i][0]=fa[i];
     82     for(int h=1;h<20;h++)
     83     {
     84         for(i=1;i<=n;i++)
     85         {
     86             s[i][h]=s[s[i][h-1]][h-1];
     87         }
     88     }
     89     for (i=1;i<=m;i++)
     90     if ((!treeEdge[i])&&(color[a[i]]!=color[b[i]])) 
     91     {
     92         sum[a[i]]--;
     93         sum[b[i]]--;
     94         sum[lca(a[i],b[i])]+=2;
     95     }
     96     for (i=1;i<=m;i++)
     97     if ((!treeEdge[i])&&(color[a[i]]==color[b[i]])) 
     98     {
     99         cnt++;
    100         sum[a[i]]++;
    101         sum[b[i]]++;
    102         sum[lca(a[i],b[i])]-=2;
    103     }
    104     memset(vis,0,sizeof(vis));
    105     for (i=1;i<=n;i++)
    106     if (!vis[i]) gao(i);
    107     int ans=0;
    108     for (i=1;i<=m;i++)
    109     if ((treeEdge[i])&&(value[i]==cnt)) ans++;
    110     if (cnt==1) ans++;
    111     printf("%d
    ",ans);
    112 } 
  • 相关阅读:
    DataGirdView 编辑项时的验证
    存储过程分面
    Android PopupWindow菜单
    Android ListView 中的checkbox
    Linq Group
    final关键字
    BroadcastReceiver
    Android Studio 快捷键
    Android Studio 基础知识
    黑客帝国代码雨实现
  • 原文地址:https://www.cnblogs.com/fzmh/p/5383729.html
Copyright © 2020-2023  润新知