牛客-沙漠点列【tarjan】
生活随笔
收集整理的這篇文章主要介紹了
牛客-沙漠点列【tarjan】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
題目鏈接:https://ac.nowcoder.com/acm/contest/1101#question
題目大意
nnn個點mmm條邊的沙漠(所有聯(lián)通子圖都是仙人掌),刪除kkk個點使得剩下的連通塊最多。
解題思路
對于圖上的每條割邊,刪去之后就可以多出一個聯(lián)通塊,所以我們就可以先刪去所有割邊。
之后圖上剩下許多個環(huán),沒兩個環(huán)之間由一個割點連接,所以我們可以用縮點雙聯(lián)通分量的方法找出所有的環(huán)。
我們發(fā)現(xiàn)對于每個環(huán)刪除一條邊之后就可以變成一條鏈,也就是我們刪除kkk條邊就會多出k?1k-1k?1個聯(lián)通塊。然后我們可以對于所有的環(huán)按照大小排序,然后從大的到小的分成鏈。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; const int N=1e6+10; struct node{int to,next; }a[N*4]; int n,m,k,tot=1,ans,c,cnt,num; int dfn[N],low[N],ls[N],cir[N]; bool mark[N*4],flag; stack<int> s; void addl(int x,int y) {a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot; } void tarjan(int x,int edge) {dfn[x]=low[x]=++cnt;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(!dfn[y]){tarjan(y,i);low[x]=min(low[x],low[y]);if(low[y]>dfn[x]){mark[i]=mark[i^1]=1;if(k) ans++,k--;}}else if(i!=(edge^1))low[x]=min(low[x],dfn[y]);} } void tarjan2(int x) {dfn[x]=low[x]=++cnt;s.push(x);for(int i=ls[x];i;i=a[i].next){if(mark[i]) continue;int y=a[i].to;if(!dfn[y]){tarjan2(y);num=0;low[x]=min(low[x],low[y]);if(low[y]>=dfn[x]){int z;do{z=s.top();num++;s.pop();}while(z!=y);num++;cir[++c]=num;}}else low[x]=min(low[x],dfn[y]);} } int main() {//freopen("2.in","r",stdin);scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0),ans++;cnt=0;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));for(int i=1;i<=n;i++)if(!dfn[i])tarjan2(i);sort(cir+1,cir+1+c);for(int i=c;i>=1;i--){if(k<2) break;ans+=min(k,cir[i])-1;k-=min(k,cir[i]);}printf("%d",ans); }總結(jié)
以上是生活随笔為你收集整理的牛客-沙漠点列【tarjan】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客-服务器需求【线段树】
- 下一篇: 51nod-猴猴吃苹果【线段树】