思路: 删除所有的有关点S的边,然后判断剩余图中是否存在环!
/*判无向图是否含有环 1.判断图中的结点数和边数 <1>若n>=m,则输出提示有回路,并返回; <2>若n<m,继续往下执行; 2.结点入队 遍历每个结点,若度数为1或0则入队,并记录下入队元素个数; 3.删除结点和边 在队列不为空的情况下,队头元素出队 <1>若该结点度数为1,则置度数为-1,并且将与它相邻接的结点度数减1,同时判断减1后该邻接结点度数是否为1,若为1则入队,同时入队元素个数加1; <2>若该结点度数为0,则直接置度数为-1; 4. 判断有无回路 <1>若入队元素个数小于结点总数,则有回路; <2>否则,无回路; */ #include <iostream> #include <stdio.h> #include <string.h> #include <queue> using namespace std; #define N 10002 int n, m,NE; int v[N],head[N]; vector<int>g[N]; struct node { int u,v,next; }Edge[N*20]; void addEdge(int u,int v) { Edge[NE].u=u,Edge[NE].v=v; Edge[NE].next=head[u]; head[u]=NE++; } int main() { int i, j, x, y,k, count,S; queue<int> q; while(scanf("%d%d%d",&n,&m,&S)!=EOF) { NE=k=0; memset(v,0,sizeof(v)); memset(head,-1,sizeof(head)); for(i = 1; i <= n; i++) g[i].clear(); for(i=1;i<=m;i++) { scanf("%d %d",&x,&y); if(!(x==S||y==S)) { addEdge(x,y); addEdge(y,x); v[x]++; v[y]++; } } while(!q.empty()) q.pop(); count = 0; for(i = 1; i <=n; i++) { if(v[i]<=1) { q.push(i); count++; }else k++; } while(!q.empty()) { int u=q.front(); q.pop(); if(v[u] == 0) v[u] = -1; else if(v[u] == 1) { v[u] = -1; for(i=head[u];i!=-1;i=Edge[i].next) { int v1=Edge[i].v; if(v1!=u) { v[v1]--; if(v[v1] == 1) { q.push(v1); count++; } } } } } if(count<m-k) printf("NO\n"); else printf("YES\n"); } return 0; } /* 5 6 3 1 2 1 5 2 3 2 4 2 5 4 5 5 6 2 1 2 1 5 2 3 2 4 2 5 4 5 */