1. 程式人生 > >poj1523:SPF——題解

poj1523:SPF——題解

inline for tdi max oot tar style ios turn

http://poj.org/problem?id=1523

這題明顯就是求割點然後求割完之後的強連通分量的個數。

割點都會求,怎麽求割完的分量個數呢?

我們可以通過萬能的並查集啊!(具體做法看代碼吧,方法不好敘述)

這樣我們查割點它所連的點一共隸屬於幾個集合即可。

(PS:讀入方式很惡心,同時請註意快速讀入)

#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef 
long long ll; inline int read(){ int x=0,w=1;char ch=0; while(ch<0||ch>9){if(ch==-)w=-1;ch=getchar();} while(ch>=0&&ch<=9){x=(x<<1)+(x<<3)+ch-0;ch=getchar();} return x*w; } const int maxn=1001; bool dis[maxn][maxn]; bool cut[20001]; int dfn[maxn]; int
low[maxn]; int fa[maxn]; int from[maxn]; int t; int big[maxn]; int to[maxn]; int find(int a){ if(a==fa[a])return a; return fa[a]=find(fa[a]); } void tarjan(int u,int f){ bool tong[maxn]={0}; from[u]=f; t++; dfn[u]=t; low[u]=t; to[t]=u; for(int v=1;v<=maxn;v++){
if(dis[u][v]){ if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); }else if(f!=v){ low[u]=min(low[u],dfn[v]); } } fa[find(u)]=find(to[low[u]]); } for(int v=1;v<=maxn;v++){ if(dis[u][v]){ if(!tong[find(v)]){ tong[find(v)]=1; big[u]++; } } } return; } int main(){ int u,v; int cnt=0; bool smg=0; while(233){ int u=read(); if(!u&&!smg)break; smg=1; if(!u){ for(int i=1;i<=maxn;i++)fa[i]=i; tarjan(1,0); int rootson=0; bool ok=0; for(int i=2;i<=maxn;i++){ int v=from[i]; if(v==1)rootson++; else{ if(low[i]>=dfn[v]&&low[i]&&dfn[i]){ cut[v]=1; ok=1; } } } if(rootson>=2){ cut[1]=1; ok=1; } cnt++; printf("Network #%d\n",cnt); if(ok==0){ printf(" No SPF nodes\n"); }else{ for(int i=1;i<=maxn;i++){ if(cut[i])printf(" SPF node %d leaves %d subnets\n",i,big[i]); } } printf("\n"); memset(cut,0,sizeof(cut)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(fa,0,sizeof(fa)); memset(from,0,sizeof(from)); memset(dis,0,sizeof(dis)); memset(big,0,sizeof(big)); memset(to,0,sizeof(to)); t=0; smg=0; continue; } int v=read(); dis[u][v]=dis[v][u]=1; } return 0; }

poj1523:SPF——題解