HIT暑期集训 tarjan,dfs序

贴一个网上讲tarjan的博客

https://blog.csdn.net/qq_34374664/article/details/77488976

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define maxn 105
#define maxm 1005
using namespace std;
stack<int>st;
int num,last[maxn],dfn[maxn],low[maxn],vis[maxn],cnt;
struct edge
{
    int to,nxt;
}e[maxm<<1];
void add(int x,int y)
{
    e[++num].to=y;
    e[num].nxt=last[x];
    last[x]=num;
}
void tarjan(int x)
{
    int i,y,tp;
    dfn[x]=low[x]=++cnt;
    st.push(x);
    vis[x]=1;
    for (i=last[x];i;i=e[i].nxt)
    {
        y=e[i].to;
        if (!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if (vis[y])
        {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if (low[x]==dfn[x])
    {
        while (!st.empty())
        {
            tp=st.top();
            printf("%d ",tp);
            vis[tp]=0;
            st.pop();
            if (tp==x) break;
        }
        printf("\n");
    }
}
int main()
{
    int i,n,m,x,y;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    for(i=1;i<=n;i++)
        if(!dfn[i])  tarjan(i);
    return 0;
}
tarjan求强连通分量模板

B    CodeForces 723F

题意:给一个联通的无向图,要求从中删边让它变为连通的树,并且s节点的度不超过ds,t节点的度不超过st。

思路:将s与t从图中分离,求剩下图中的连通块,可知每个连通块只存在三种情况,①与s连边,②与t连边,③与s和t均连边。

对于只与s或t相连的连通块,直接连边即可。

对于与s和t均相连的连通块,若s与t不连通,则将连通块与s、t各连一条边;若s与t已经连通,则选择s、t中度数未超过要求的点连边(只连一条边)。

若不存在与s和t均联通的连通块,则在s与t之间连边(因为是连通图,必定有边)。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200005
#define maxm 400005
using namespace std;
int num,to[maxm<<1],nxt[maxm<<1],last[maxn];
int vis[maxn],cnt,vs[maxn],vt[maxn],s,t,tot;
struct node
{
    int x,y;
}ans[maxn];
void add(int x,int y)
{
    to[++num]=y;nxt[num]=last[x];last[x]=num;
}
void dfs(int u)
{
    int i,v;
    vis[u]=1;
    for (i=last[u];i;i=nxt[i])
    {
        v=to[i];
        if (v==s) vs[cnt]=u;
        if (v==t) vt[cnt]=u;
        if (!vis[v]) 
        {
            ans[++tot].x=u;ans[tot].y=v;
            dfs(v);
        }
     }
}
int main()
{
    int i,j,x,y,n,m,ds,dt,flag=0,both=0;
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++) 
    {
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    scanf("%d%d%d%d",&s,&t,&ds,&dt);
    vis[s]=1;vis[t]=1; 
    for (i=1;i<=n;i++)
        if (!vis[i]) 
        {
            cnt++;
            dfs(i);    
        }
    for (i=1;i<=cnt;i++)
    {
        if (vs[i] && !vt[i])
        {
            ans[++tot].x=vs[i];ans[tot].y=s;
            ds--;
        }
        else if (!vs[i] && vt[i])
        {
            ans[++tot].x=vt[i];ans[tot].y=t;
            dt--;
        }
        else if (!vs[i] && !vt[i]) flag=1;
        else both++;
    }
    if (flag || dt<=0 || ds<=0 || both+1>ds+dt)
    {
        printf("No\n");
        return 0;
    }
    if (!both)
    {
        ans[++tot].x=s;ans[tot].y=t;
    }
    else 
    {
        flag=0;
        for (i=1;i<=cnt;i++)
            if (vs[i] && vt[i])
            {
                if (!flag)
                {
                    ans[++tot].x=vs[i];ans[tot].y=s;
                    ans[++tot].x=vt[i];ans[tot].y=t;
                    flag=1;
                    ds--;dt--;
                }
                else 
                {
                    if (ds)
                    {
                        ans[++tot].x=vs[i];ans[tot].y=s;
                        ds--;
                    }
                    else 
                    {
                        ans[++tot].x=vt[i];ans[tot].y=t;
                        dt--;
                    }
                }
            }
    }
    printf("Yes\n");
    for (i=1;i<=tot;i++) printf("%d %d\n",ans[i].x,ans[i].y);
    return 0;
 } 
View Code

D    CodeForces 570D

E    CodeForces 652E

G    ZOJ 4097

H    CodeForces 383C

I    UVA 1108

posted @ 2020-08-12 12:46  lsy_kk  阅读(109)  评论(0)    收藏  举报