トピックリンク:https://www.luogu.com.cn/problem/P3388
本当に速いハードウェアアルゴリズムをtarjan、時間の複雑さはO(| V | + | E |)ので、1E4 2E5のノードは、図完全に楽勝ORZ ORZエッジ
tarjanは一度だけ前に使用しているため、必ずしも通信していない点マップをカットしようとせずに、その訪問tarjanを継続するためにはポイントがありません、この時間は、私は、数回WA、私はデフォルトのパラメータを設定しますuが1でDFSツリーを構築し始めました=。すべての父の唯一のルートは、我々が独自に学んだ、それを識別できるようにすることを、その数に等しいです。次に、ロールバックサイドを処理する際に使用される場合、次の証明tarjanである①、ロー[U] =分(低[U]、低[V]) (使用強連結成分)の代わりに②、低[U =分(低[U] 、DFN [V]) 、次にどのようなエラーのであろう。
我々は両方のアナログとTarjanのアルゴリズム、1はlow[u] = min( low[u], low[v] );
、1ですlow[u] = min( low[u], dfn[v] );
。(参考羅Guboをオフに証明します)
項目1:
①DFS(1)、DFN [1] = 1、ロー[1] = 1。
②DFS(2)、DFN [2] = 2、ロー[2] = 2。
③DFS(3)、DFN [3] = 3、低い[3] = 3。
[3] = 1> 1、低 - ④背面側3を見つけました。
⑤DFS(4)、DFN [4] = 4、ロー[4] = 4。
⑥DFS(5)、DFN [5] = 5、ロー[5] = 5。
[5] = 1>図3に示すように、低 - ⑦背側5を発見しました。
⑧DFS(5)の端部、バックDFS(4)、ロー[4] = 1。
⑨DFS(4)エンド、バックDFS(3)、低い[3] = 1。
⑩DFS(3)末端、これまでにないカットポイントが見つかりません。
ランク2:
①DFS(1)、DFN [1] = 1、ロー[1] = 1。
②DFS(2)、DFN [2] = 2、ロー[2] = 2。
③DFS(3)、DFN [3] = 3、低い[3] = 3。
[3] = 1> 1、低 - ④背面側3を見つけました。
⑤DFS(4)、DFN [4] = 4、ロー[4] = 4。
⑥DFS(5)、DFN [5] = 5、ロー[5] = 5。
[5] = 3>図3に示すように、低 - ⑦背側5を発見しました。
⑧DFS(5)の端部、バックDFS(4)、ロー[4] = 3。
⑨DFS(4)エンド、バックDFS(3)、ロー[4]> = DFN [3]、見られるカットポイント3、低い[3] = 1。
そして、この図は、正しい答えは:3カット点です。
だから、最初の方法は、我々はハックさせていただきます。
DFNの条件でプラス側が[V] <DFN [U]は、時間効率が明らかである約10%改善されている場合にのみ側面は、親ノードのロールバックに到達するので、第二に、私は、ロールバックこれは、ノードの前にアクセスされるが、このノードは既にFAノードが処理されていません。
コードは以下の通りであります:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define mp(a,b) make_pair((a),(b)) 17 #define P pair<int,int> 18 #define dbg(args) cout<<#args<<":"<<args<<endl; 19 #define inf 0x3f3f3f3f 20 const int maxn=2e4+10; 21 int n,m,t; 22 inline int read(){ 23 int ans=0,w=1; 24 char ch=getchar(); 25 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 26 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 27 return ans*w; 28 } 29 int low[maxn],dfn[maxn],iscut[maxn],head[maxn],nxt[200010]; 30 int cnt=0; 31 int ans=0; 32 struct node{ 33 int u,v; 34 }p[200010]; 35 int e=0; 36 void addedge(int x,int y) 37 { 38 p[e].u=x; 39 p[e].v=y; 40 nxt[e]=head[x]; 41 head[x]=e++; 42 } 43 void tarjan(int u,int fa) 44 { 45 dfn[u]=low[u]=++cnt; 46 int child=0; 47 for(int i=head[u];~i;i=nxt[i]) 48 { 49 int v=p[i].v; 50 if(!dfn[v]) 51 { 52 if(fa==u)child++; 53 tarjan(v,u); 54 low[u]=min(low[v],low[u]); 55 if(low[v]>=dfn[u]&&u!=fa)iscut[u]=1; 56 } 57 else if(dfn[v]<dfn[u]&&v!=fa) 58 { 59 low[u]=min(low[u],dfn[v]); 60 } 61 } 62 if(u==fa&&child>1)iscut[u]=1; 63 } 64 int main() 65 { 66 //freopen("input.txt","r",stdin); 67 //freopen("output.txt","w",stdout); 68 std::ios::sync_with_stdio(false); 69 n=read(),m=read(); 70 int x,y; 71 cnt=0; 72 ans=0; 73 mem(low,0); 74 mem(dfn,0); 75 mem(iscut,0); 76 mem(head,-1); 77 mem(nxt,-1); 78 f(i,1,m) 79 { 80 x=read(),y=read(); 81 addedge(x,y); 82 addedge(y,x); 83 } 84 f(i,1,n) 85 { 86 if(!dfn[i])tarjan(i,i);//图不一定连通,所以每个连通分量都要tarjan一次 87 } 88 f(i,1,n) 89 { 90 if(iscut[i])ans++; 91 } 92 pf("%d\n",ans); 93 f(i,1,n) 94 if(iscut[i])pf("%d ",i); 95 return 0; 96 }