洛谷 P3388 【模板】割点(割顶)题解
今天学了割点,就A了这道板子,比较难理解的地方就在于如果是根节点就要找两个点来满足low[y]>=dfn[x],如果不是就只需找一个点来满足。Tarjan(i,i)中第一个i是开始搜索的点而第
二个i代表根节点,就是这棵搜索树的根,虽然一开始值是一样的,但x是要随着搜索向下找的,而根节点在搜索过程中不变。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 100010 6 #define maxm 500010 7 using namespace std; 8 inline int read() 9 { 10 int x=0; 11 bool f=1; 12 char c=getchar(); 13 for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 14 for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 15 if(f) return x; 16 return 0-x; 17 } 18 inline void write(int x) 19 { 20 if(x<0){putchar('-');x=-x;} 21 if(x>9)write(x/10); 22 putchar(x%10+'0'); 23 } 24 struct node 25 { 26 int to,nex; 27 }edge[2*maxm]; 28 int dfn[maxn],low[maxn],st[maxn],inn[maxn],head[maxm],ans[maxn]; 29 int n,m,cnt,res,num; 30 inline void add(int u,int v) 31 { 32 cnt++; 33 edge[cnt].to=v; 34 edge[cnt].nex=head[u]; 35 head[u]=cnt; 36 } 37 inline void Tarjan(int x,int root) 38 { 39 dfn[x]=low[x]=++num; 40 int flag=0; 41 for(int i=head[x];i!=-1;i=edge[i].nex) 42 { 43 int y=edge[i].to; 44 if(!dfn[y]) 45 { 46 Tarjan(y,root); 47 low[x]=min(low[x],low[y]); 48 if(low[y]>=dfn[x]&&x!=root) ans[x]=true; 49 if(x==root) flag++; 50 } 51 else low[x]=min(low[x],dfn[y]); 52 } 53 if(x==root&&flag>=2) ans[root]=true; 54 } 55 int main() 56 { 57 memset(head,-1,sizeof(head)); 58 n=read();m=read(); 59 for(int i=1;i<=m;i++) 60 { 61 int u,v; 62 u=read();v=read(); 63 add(u,v); 64 add(v,u); 65 } 66 for(int i=1;i<=n;i++) 67 if(!dfn[i]) 68 Tarjan(i,i); 69 for(int i=1;i<=n;i++) 70 if(ans[i]) 71 res++; 72 write(res); 73 printf("\n"); 74 for(int i=1;i<=n;i++) 75 if(ans[i]) 76 { 77 write(i); 78 printf(" "); 79 } 80 return 0; 81 }
请各位大佬斧正(反正我不认识斧正是什么意思)