[8.21NOIP模拟赛]决战【tarjan】
生活随笔
收集整理的這篇文章主要介紹了
[8.21NOIP模拟赛]决战【tarjan】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題目大意
nnn個(gè)點(diǎn)mmm條邊的聯(lián)通圖,去掉一個(gè)點(diǎn)使得其變?yōu)橐豢脴?/p>
求能去掉哪些點(diǎn)
解題思路
首先去掉后就是一棵n?1n-1n?1個(gè)節(jié)點(diǎn)的樹,也就是有n?2n-2n?2條邊,這樣我們就需要去掉m?n+2m-n+2m?n+2條邊,也就是去掉入度為m?n+2m-n+2m?n+2的點(diǎn)。
但是需要去掉后圖任然是聯(lián)通圖,也就是去掉的是非割點(diǎn),tarjantarjantarjan求割點(diǎn)即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10; struct node{int to,next; }a[N*2]; int n,m,tot,cnt,in[N],ls[N],dfn[N],low[N]; bool mark[N]; void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot; } void tarjan(int x){dfn[x]=low[x]=++cnt;int flag=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);if(dfn[x]<=low[y]){flag++;if((x!=1||flag>1)&&!mark[x])mark[x]=1;}}else low[x]=min(low[x],dfn[y]);} } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);in[x]++;in[y]++;}tarjan(1);int ans=0;for(int i=1;i<=n;i++)if(!mark[i]&&in[i]==m-n+2)ans++;printf("%d\n",ans);for(int i=1;i<=n;i++)if(!mark[i]&&in[i]==m-n+2)printf("%d ",i); }總結(jié)
以上是生活随笔為你收集整理的[8.21NOIP模拟赛]决战【tarjan】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 燕郊属于哪里 关于燕郊的简介
- 下一篇: nssl1511-我的世界【堆,贪心】