题意:
求给出的两点u,v间的割点个数,如果u,v不再同一个连通图中,输出-1;
题解:
昨天刚看完DFS求无向图的割点个数,碰巧看到了这道题,刷刷刷撸出一发代码,本地测试,通过,ok,提交,40分........
后来仔细想了一下,对于求节点u,v间的割点个数,如果u有多条路径可以到达v,那么对于某一割点 i ,将其删去后,u,v不一定不连通。
那么如果再从所有的割点中判断其是否为u,v间的割点,岂不是太麻烦了;
举足无措,找大佬博客想看看他们是怎么处理这种情况的,翻了好几篇博客,暴力据多,比较好的一篇就是通过DFS求出从u到v的总路径个数totPath,
对于属于u,v路径上的点 i ,记录其出现的次数为cnt[ i ],如果cnt[ i ]==totPath说明其为u,v路径上的割点;
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 const int maxn=1e3+50; 7 8 int n,m; 9 int cnt[maxn]; 10 int path[maxn]; 11 bool vis[maxn]; 12 int num; 13 int head[maxn]; 14 struct Edge 15 { 16 int to; 17 int next; 18 }G[4*maxn]; 19 void addEdge(int u,int v) 20 { 21 G[num].to=v; 22 G[num].next=head[u]; 23 head[u]=num++; 24 } 25 26 void DFS(int u,int aimPoint,int k,int &totPath) 27 { 28 if(u == aimPoint)//来到目标节点v 29 { 30 for(int i=0;i < k-1;++i) 31 cnt[path[i]]++;//将路径上的点出现的次数++ 32 totPath++; 33 return ; 34 } 35 for(int i=head[u];~i;i=G[i].next)//搜索所有可能的路径 36 { 37 int v=G[i].to; 38 if(!vis[v]) 39 { 40 vis[v]=true; 41 path[k]=v; 42 DFS(v,aimPoint,k+1,totPath); 43 vis[v]=false; 44 } 45 } 46 } 47 int Solve() 48 { 49 int u,v; 50 scanf("%d%d",&u,&v); 51 int totPath=0; 52 DFS(u,v,0,totPath); 53 54 if(totPath == 0) 55 return -1; 56 57 int ans=0; 58 for(int i=1;i <= n;++i) 59 ans += cnt[i] == totPath ? 1:0; 60 61 return ans; 62 } 63 void Init() 64 { 65 num=0; 66 mem(head,-1); 67 mem(vis,false); 68 mem(cnt,0); 69 } 70 int main() 71 { 72 while(~scanf("%d%d",&n,&m)) 73 { 74 Init(); 75 for(int i=1;i <= m;++i) 76 { 77 int u,v; 78 scanf("%d%d",&u,&v); 79 addEdge(u,v); 80 addEdge(v,u); 81 } 82 printf("%d ",Solve()); 83 } 84 return 0; 85 }