题意:给出一张无向图,求添加多少条边后任意减去一条边,整张图仍联通。
解:第一个想到的是割边,想对于一条割边,将上下两点连起来,所以输出割边的数量。画了画图觉得不对,对于一条链,把两头连起来就满足要求了,应该求这张图有多少线头,然后把线头数量除以2。然后删掉割边的代码,写着写着发现和上一题相同起来……割点割边碰到了再练吧。
注意这次是无向图,所以不能求出度为0,应该求出度为1.
代码:
#include <algorithm> #include <stack> #include <vector> #include <stdio.h> using namespace std; #define maxx 10005 #define maxn 10005 #define maxm 50005 #define inf 0x3f3f3f3f int n,m; vector<int> e[maxm]; int dfn[maxn]={0},low[maxn]={0}; int cnt=0,vis[maxn]={0}; int colornum=0,color[maxn]={0},num[maxn]={0}; int out[maxn]={0}; stack<int> s; void paint(int x){ s.pop(); vis[x]=0; color[x]=colornum; num[colornum]++; } void tarjan(int now,int fa){ s.push(now); vis[now]=1; low[now]=dfn[now]=++cnt; for(int i=0;i<e[now].size();i++){ int to=e[now][i]; if(to==fa) continue; if(!dfn[to]){ tarjan(to,now); low[now]=min(low[now],low[to]); } else if(vis[to]) low[now]=min(low[now],dfn[to]); } if(low[now]==dfn[now]){ colornum++; while (s.top()!=now) paint(s.top()); paint(now); } } signed main() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ int x,y; scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0); for(int i=1;i<=n;i++){ for(int j=0;j<e[i].size();j++){ int to=e[i][j]; if(color[to]!=color[i]) out[color[i]]++; } } int ans=0; for(int i=1;i<=colornum;i++) if(out[i]==1){ ans++; } printf("%d\n",(ans+1)/2); return 0; }