bzoj1718(边双连通分量+贪心)

题面是图不好截QAQ
就是加点使图变成一个大的边双
先根据已有的边双缩点
会形成一棵树
贪心连叶子结点
答案= num+1/2 ( n u m + 1 ) / 2

#include<bits/stdc++.h>
using namespace std;
int n , m , linkk[5100] ,t;
int dfn[5100] , low[5100] , tt;
int color[5100] , tot , du[5100];
struct node{
    int n , x , y;
    bool flag;
}e[21000]; 
int read() {
    bool flag=true;int num=0;char c=getchar(); 
    for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=false; 
    for(;c>='0'&&c<='9';c=getchar()) num=(num<<3)+(num<<1)+c-48; 
    if(flag) return num;    else return -num; 
} 
void insert(int x,int y){
    e[++t].x = x;e[t].y = y;e[t].n = linkk[x];linkk[x] = t;
    e[++t].y = x;e[t].x = y;e[t].n = linkk[y];linkk[y] = t;
    return;
}
void trajan(int x,int fa){
    dfn[x] = low[x] = ++tt;
    for(int i = linkk[x];i;i = e[i].n)
       if(!dfn[e[i].y]){
           int y = e[i].y;
           trajan( y , i );
           low[x] = min( low[x] , low[y] ); 
           if(low[y] > dfn[x]){
              e[i].flag = true ,
              e[i ^ 1].flag = true;
           }
       }
       else
         if( (i ^ 1) != fa)
           low[x] = min( low[x] , dfn[e[i].y] );
    return;
}
void dfs(int x){
    color[x] = tot;
    for(int i = linkk[x];i;i = e[i].n)
       if(!color[e[i].y] && !e[i].flag)
          dfs(e[i].y);
}
void make_node(){
    t = 0;
    memset(linkk,0,sizeof(linkk));
    for(int i = 1;i <= m;++i){
        int j = i * 2; 
        int x = e[j].x , y = e[j].y;
        if(color[x] != color[y]) 
          insert( color[x] , color[y] ) ,
          du[color[x]]++,du[color[y]]++;
    }
    return;
}
int get(){
    int sum = 0;
    for(int i = 1;i <= tot;++i){
        bool flag = true;
        int k = e[linkk[i]].y;
        for(int j = linkk[i];j;j = e[j].n)
          if(e[j].y != k){
             flag = false;
          }
        if(flag) sum++;
    }
    return sum;
}
int main(){
    n = read();m = read();t = 1;
    for(int i = 1;i <= m;++i){
        int x = read() , y = read();
        insert( x , y );
    }
    trajan( 1 , 0 );
    for(int i = 1;i <= n;++i)
      if(!color[i]) ++tot , dfs(i);
    make_node();
    int num = 0;
    for(int i = 1;i <= tot;++i)
       num += (du[i] == 1);
    printf("%d",(num+1)/2);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值