codevs 2822(tarjan)

来源:互联网 发布:搭建php运行环境 编辑:程序博客网 时间:2024/06/06 01:19

传送门
题解:
第一问:输出size大于1的强连通分量的个数(注意测试点1的特判,此测试点没有size大于1的连通分量。。。)
第二问:统计出度为0的分量个数,由于整个图连通,所以出度为0的分量一定能被其余所有分量走到,当且仅当这样的分量只有一个,大于一个则输出-1(可以理解为出现了“分叉”的情况)。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<stack>#include<vector>using namespace std;const int MAXN=200006,MAXM=200006;int n,m,head[MAXN],edge=0;struct EDGE {    int v,nxt;}e[MAXM];bool ins[MAXN];int dfn[MAXN],low[MAXN],bel[MAXN],tim=0,snt=0;inline int read() {    int x=0;char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();    return x;}inline void adde(int u,int v) {    e[edge].nxt=head[u],e[edge].v=v,head[u]=edge++;}stack<int> S;vector<int> G[MAXN];int out[MAXN];void dfs(int p) {    low[p]=dfn[p]=++tim;    S.push(p),ins[p]=true;    for (int i=head[p];~i;i=e[i].nxt) {        int v=e[i].v;        if (!dfn[v]) {            dfs(v);            low[p]=min(low[p],low[v]);        }        else if (ins[v]) low[p]=min(low[p],dfn[v]);    }    if (low[p]==dfn[p]) {        ++snt;        while (true) {            int t=S.top();            S.pop();            bel[t]=snt;            ins[t]=false;            G[snt].push_back(t);//printf("size:%d\n",G[snt].size());            if (t==p) break;        }    }}int main() {    memset(head,-1,sizeof(head));    memset(ins,false,sizeof(ins));    memset(dfn,0,sizeof(dfn));    memset(out,0,sizeof(out));    n=read(),m=read();    for (register int i=0;i<m;++i) {        int u=read(),v=read();        adde(u,v);    }    for (register int i=1;i<=n;++i) G[i].clear();    for (register int i=1;i<=n;++i) {        if (!dfn[i]) dfs(i);    }    for (register int p=1;p<=n;++p)        for (int i=head[p];~i;i=e[i].nxt) {            int v=e[i].v;            if (bel[p]^bel[v]) ++out[bel[p]];        }    int f=0,pos,ans=0,judge=true;    for (int i=1;i<=snt;++i) {        if (G[i].size()>1)            ++ans;        if (!out[i]) {            ++f,pos=i;            if (f==2) judge=false;        }    }    if (!ans||!judge) {printf("%d\n%d\n",ans,-1);return 0;}    sort(G[pos].begin(),G[pos].end());    printf("%d\n",ans);    for (int i=0;i<G[pos].size();++i)        printf("%d ",G[pos][i]);    puts("");    return 0;}
原创粉丝点击