Description
Input
Output
Sample Input
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7
Sample Output
2
Hint
1 2 3 +---+---+ | | | | 6 +---+---+ 4 / 5 / / 7 +Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.
1 2 3 +---+---+ : | | : | | 6 +---+---+ 4 / 5 : / : / : 7 + - - - -Check some of the routes:
Source
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #define LL long long using namespace std; const int MaxN = 10100; const int MaxM = 5100; // 建图 typedef struct node { int v; int next; }Line; Line Li[MaxN*2]; int Belong[MaxM];//判断所属的双连通的集合 //回到最优先遍历度最小的节点和记录点DFS的顺序 int low[MaxM],dfn[MaxM]; int Head[MaxM],top; int pre[MaxM]; //并查集 int vis[MaxM],Num;//标记点的状态 int Bridge[MaxM][2],NumB;//记录图中的桥 void AddEdge(int u,int v)// 建边 { Li[top].v=v; Li[top].next=Head[u]; Head[u]=top++; Li[top].v=u; Li[top].next=Head[v]; Head[v]=top++; } int Find(int x)// 路径压缩 { return pre[x]==-1?x:pre[x]=Find(pre[x]); } void Union(int x,int y) { int Fx = Find(x); int Fy = Find(y); if(Fx!=Fy) { pre[Fx] = Fy; } } void dfs(int u,int father) { low[u]=dfn[u]=Num++; vis[u]=1;//表示已经遍历但是没有遍历完子女 for(int i=Head[u];i!=-1;i=Li[i].next) { int j=Li[i].v; if(vis[j]==1&&j!=father)// 回到的祖先 { low[u]=min(low[u],dfn[j]); } if(vis[j]==0) { dfs(j,u); low[u]=min(low[j],low[u]); if(low[j]<=dfn[u])//说明是双连分量中的边 { Union(u,j); } if(low[j]>dfn[u])//桥 { Bridge[NumB][0]=j; Bridge[NumB++][1]=u; } } } vis[u]=2; } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { top=0; int u,v; memset(Head,-1,sizeof(Head)); memset(pre,-1,sizeof(pre)); for(int i=1;i<=m;i++) { scanf("%d %d",&u,&v); AddEdge(u,v); } memset(vis,0,sizeof(vis)); memset(Belong ,-1 ,sizeof(Belong)); Num = 0 ; NumB=0 ; dfs(1,0); Num = 0; for(int i=1;i<=n;i++) { int k=Find(i);//给双连通分量集合编号 if(Belong[k]==-1) { Belong[k]=++Num; } Belong[i]=Belong[k]; } memset(vis,0,sizeof(vis)); for(int k=0;k<NumB;k++) { int i=Bridge[k][0]; int j=Bridge[k][1]; vis[Belong[i]]++; vis[Belong[j]]++; } int ans = 0; for(int i=1;i<=n;i++) { if(vis[i]==1) { ans++; } } printf("%d\n",(ans+1)/2); } return 0; }