CodeForces 51F Caterpillar

time limit per test 2  seconds
memory limit per test  256 megabytes
input  standard input
output  standard output

An undirected graph is called a caterpillar if it is a connected graph without cycles and it has such a path p that any vertex is located at a distance of at most 1 from the path p. The caterpillar can contain loops (edges from a vertex to itself) but cannot contain multiple (parallel) edges.

The picture contains an example of a caterpillar:

You are given an undirected graph G. You are allowed to do a merging operations, each such operation merges two vertices into one vertex. For that two any vertices a and b (a ≠ b) are chosen. These verteces are deleted together with their edges (which are incident to at least one of the vertices a or b) but a new vertex w is added together with edges (x, w) for each edge (a, w) and/or (b, w). If there was the edge (a, b) it transforms to the loop (w, w). The resulting graph (after the merging operation) may contain multiple (parallel) edges between pairs of vertices and loops. Let us note that this operation decreases the number of vertices of graph by 1 but leaves the number of edges in the graph unchanged.

The merging operation can be informally described as a unity of two vertices of the graph into one with the natural transformation of the graph edges.

You may apply this operation consecutively and make the given graph to be a caterpillar. Write a program that will print the minimal number of merging operations required to make the given graph a caterpillar.

Input

The first line contains a pair of integers nm (1 ≤ n ≤ 2000;0 ≤ m ≤ 105), where n represents the number of vertices in the graph andm is the number of edges in it. Then the following m lines contain edge descriptions, one edge description per line. Every line contains a pair of integers ai, bi (1 ≤ ai, bi ≤ n;ai ≠ bi), ai, bi which represent the indices of the vertices connected by the edge. The vertices are numbered from 1 to n. In the given graph it will be no more than one edge between any pair of vertices. The given graph is not necessarily connected.

Output

Print the minimal required number of operations.

Examples
input
4 4
1 2
2 3
3 4
4 2
output
2
input
6 3
1 2
3 4
5 6
output
2
input
7 6
1 2
2 3
1 4
4 5
1 6
6 7
output
1

 

缩点

  目标状态是一棵树,可以有自环,不能有重边。tarjan缩点后,原图形成一片森林,对于每一棵树,它最多可以保留点数res=直径上的点数+其他叶子结点树。处理森林中的每一棵树,ans=total-res

_____

  刚开始没察觉到有森林,按照树处理,WA飞

  之后因为缩点后重边加多了,T飞

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 #include<vector>
  7 using namespace std;
  8 const int mx[5]={0,1,0,-1,0};
  9 const int my[5]={0,0,1,0,-1};
 10 const int mxn=2100;
 11 int read(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 struct edge{
 18     int v,nxt;
 19 }e[200010];
 20 int hd[mxn],mct=0;
 21 void add_edge(int u,int v){
 22     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 23 }
 24 int mp[mxn][mxn];
 25 int n,m;
 26 int dtime=0;
 27 int low[mxn],dfn[mxn];
 28 int belone[mxn],cnt;
 29 int st[mxn],top=0;
 30 void tarjan(int u,int fa){
 31     dfn[u]=low[u]=++dtime;
 32     st[++top]=u;
 33     for(int i=hd[u];i;i=e[i].nxt){
 34         int v=e[i].v;
 35         if(v==fa)continue;
 36         if(!dfn[v]){
 37             tarjan(v,u);
 38             low[u]=min(low[u],low[v]);
 39         }
 40         else low[u]=min(low[u],dfn[v]);
 41     }
 42     if(dfn[u]==low[u]){
 43         cnt++;
 44         int v=0;
 45         do{
 46             v=st[top--];
 47             belone[v]=cnt;
 48         }while(v!=u);
 49     }
 50     return;
 51 }
 52 vector<int>eg[mxn];
 53 int dis[mxn];
 54 bool vis[mxn];int kct=0;
 55 int tg=0;
 56 void DFS(int u,int fa){
 57     vis[u]=1;
 58     dis[u]=dis[fa]+1;
 59     if(dis[u]>dis[tg])tg=u;
 60     for(int i=0;i<eg[u].size();i++){
 61         int v=eg[u][i];
 62         if(v==fa)continue;
 63         DFS(v,u);
 64     }
 65     return;
 66 }
 67 int pos1,pos2;
 68 int outd[mxn];
 69 int solve(){
 70     if(cnt==1)return n-1;
 71     int i,j;
 72     for(i=1;i<=n;i++){
 73         for(j=hd[i];j;j=e[j].nxt){
 74             int v=e[j].v;
 75             if(mp[belone[i]][belone[v]])continue;
 76             if(belone[i]!=belone[v]){
 77                 eg[belone[i]].push_back(belone[v]);
 78                 mp[belone[i]][belone[v]]=1;//防止加重边 
 79                 outd[belone[i]]++;
 80             }
 81         }
 82     }
 83     int res=0;
 84     for(i=1;i<=cnt;i++)if(outd[i]==1) res++;//叶子节点数
 85     for(i=1;i<=cnt;i++){
 86         if(vis[i])continue;
 87         kct++;//联通块计数 
 88         //
 89         tg=0;
 90         DFS(i,0);
 91         pos1=tg;
 92         tg=0;
 93         DFS(pos1,0);
 94         pos2=tg;
 95         //求直径 
 96         if(dis[pos2]<2)res++;
 97         else res+=dis[pos2]-2;
 98     }
 99     return n-res+kct-1;
100 }
101 int main()
102 {
103     n=read();m=read();
104     int i,j,u,v;
105     for(i=1;i<=m;i++){
106         u=read();v=read();
107         add_edge(u,v);
108         add_edge(v,u);
109     }
110     for(i=1;i<=n;i++)
111         if(!dfn[i])tarjan(i,0);
112     int ans=solve();
113     printf("%d\n",ans);
114     return 0;
115 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6131084.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值