题意:给你n个点,r条无向边,问最少需要添加几条边使即使删除一条边,依旧能够从一点到达任意点
题解:无向图强连通建边,只要将整个图建成一个边双连通图,那么删除任意一条边依旧还是能够从一点到达任意点
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const double Pi=3.14159265; const double e=2.71828182; const int N=3e3+5; const ull base=163; const ll INF=0x3f3f3f3f; using namespace std; int head[N],nx[N],to[N]; int low[N],dfn[N]; int tot=1; int vis[N]; int sta[N],size=0,num=0; int com[N]; void add(int u,int v){ to[tot]=v; nx[tot]=head[u]; head[u]=tot++; } void dfs(int x,int step,int pre){ vis[x]=1; dfn[x]=low[x]=step; sta[size++]=x; int flag=0; for(int i=head[x];i;i=nx[i]){ int v=to[i]; if(v==pre&&!flag){ flag=1; continue; } if(!vis[v])dfs(v,step+1,x); if(vis[v]==1)low[x]=min(low[x],low[v]); } if(dfn[x]==low[x]){ int k; num++; do{ k=sta[--size]; com[k]=num; }while(k!=x); } } void tarjan(int n){ for(int i=1;i<=n;i++) if(!vis[i])dfs(i,0,-1); } int in[N],out[N]; void init(int n){ tot=1; size=num=0; memset(head,0,sizeof(head)); for(int i=1;i<=n;i++)vis[i]=in[i]=out[i]=0; } int main(){ fio; //int oo=0; int n,r; while(cin>>n>>r){ init(n); while(r--){ int u,v; cin>>u>>v; add(u,v); add(v,u); } tarjan(n); // cout<<"Output for Sample Input "<<++oo<<endl; for(int u=1;u<=n;u++){ for(int i=head[u];i;i=nx[i]){ int v=to[i]; if(com[v]==com[u])continue; else{ in[com[v]]++; out[com[u]]++; } } } int ans=0; for(int i=1;i<num;i++){ //cout<<in[i]<<" "<<out[i]<<endl; if(in[i]==1&&out[i]==1)ans++; } cout<<(ans+1)/2<<endl; } return 0; }