边双连通分量
这题的数据量比题目写的小,这题还需要判重,
2个确定的点之间的任何边都算same path,唔,不知道为什么,很弱看不懂题目。。。。
所以要先去重边,然后dfs求出桥,再dfs求出边双连通分量(只要不经过桥就行了)
问加多少条边使得任意两点都有两条不同边的路,就是求一个双连通分量
所以求出边双连通分量,然后缩点形成新图,
新图上度数为1的节点(即叶节点)数目为ans
(ans+1)/2 即为答案
View Code #include <cstdio> #include <cstring> #include <iostream> #include <vector> #include <stack> #include <map> using namespace std; #define MAXN 1000+5 #define MAXM 10050*10 int F,R; int e; vector<int>G[MAXN],P[MAXN]; int dfs_clock,bcc_cnt; int pre[MAXN]; int first2[MAXN]; int T[MAXN]; int M[MAXN][MAXN]; int dfs1(int u,int fa) { int lowu=pre[u]=++dfs_clock; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!pre[v]) { int lowv=dfs1(v,u); lowu=min(lowu,lowv); if(lowv>pre[u]) { P[v].push_back(u); P[u].push_back(v); } } else if(pre[v]<pre[u]&&v!=fa) { lowu=min(pre[v],lowu); } } return lowu; } void dfs2(int u,int fa) { T[u]=bcc_cnt; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; bool f=true; for(int j=0;j<P[u].size();j++) { int vv=P[u][j]; if(v==vv) { f=false;break; } } if(!f||T[v])continue; dfs2(v,u); } } void find_bcc(int n) { dfs_clock=0,bcc_cnt=0; memset(pre,0,sizeof(pre)); memset(T,0,sizeof(T)); for(int i=1;i<=n;i++) if(!pre[i]) dfs1(i,-1); for(int i=1;i<=n;i++) if(!T[i]) { bcc_cnt++; dfs2(i,-1); } } int ans[MAXN]; int main() { // freopen("in.txt","r",stdin); while(~scanf("%d%d",&F,&R)) { int a,b; memset(M,0,sizeof(M)); for(int i=0;i<MAXN;i++){ G[i].clear(); P[i].clear(); } for(int i=0;i<R;i++) { scanf("%d%d",&a,&b); if(M[a][b]==1)continue; M[a][b]=M[b][a]=1; G[a].push_back(b); G[b].push_back(a); } find_bcc(F); memset(ans,0,sizeof(ans)); for(int i=1;i<=F;i++) for(int j=0;j<G[i].size();j++) { int v=G[i][j]; if(T[i]!=T[v]) ans[T[i]]++; } int re=0; for(int i=1;i<=bcc_cnt;i++) if(ans[i]==1) re++; printf("%d\n",(re+1)/2); } }