codeforces 131D - Subway

题意



给你一个无向图,n个点n条边,保证图连通,并且有且只有有一个环,求出每个点距离环的距离


分析:第一次写这样的问题,之前听说过环缩点但是不知道具体算法是什么样子的。

大体算法是两次bfs,第一次找出属于环的点,第二次是将环向外bfs。

第一次bfs:将所有度为1的点加入队列中(因为度为1的点必定不是环里的点)进行bfs,如果遇到度>=3的点,先将这个点的度剪去1,直到这个点的度为2的时候才将其加入队列,并且标记vis 。

因为如果的环上的点,度不可能被减为2。环内部的点度虽然为2但是不会被访问到。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define MAX_N        3005
#define MAX_M         10007
struct ed
{
    int to;
    int next; 
}edge[MAX_M];
int n;
int stu[MAX_N];
int col = 0;
int ednum[MAX_N];
bool vis[MAX_N];
void addedge(int u , int v)
{
    edge[col].to = v;
    edge[col].next = stu[u];
    stu[u] = col++;
}
void bfs(){
    queue<int> que;
    for (int i = 1; i <= n ; ++i)
    {
        if(ednum[i] == 1){
            que.push(i);
            vis[i] = true;
        }
    }
    while(!que.empty())
    {
        int tem =  que.front();
        que.pop();
        for (int i = stu[tem]; i !=-1 ; i = edge[i].next)
        {
            if(vis[edge[i].to])
                continue;
            if(ednum[edge[i].to]==2)
            {
                que.push(edge[i].to);
                vis[edge[i].to] = true;
            }
            else
                ednum[edge[i].to]--;
        }
    }
}
int ans[MAX_N];
void bfs2()
{
    queue<int> que;
    for (int i = 1; i <= n ; ++i)
    {
        if(!vis[i])
            que.push(i);
    }
    while(!que.empty())
    {
        int tem =  que.front();
        que.pop();
        for (int i = stu[tem]; i !=-1 ; i = edge[i].next)
        {
            if(!vis[edge[i].to])
                continue;
            vis[edge[i].to] = false;
            que.push(edge[i].to);
            ans[edge[i].to] = ans[tem]+1;
        }
    }
}
int main(int argc, char const *argv[])
{
    memset(stu,-1,sizeof(stu));
    scanf("%d",&n);
    int fir, las ;
    for (int i = 0; i < n; ++i)
    {
        scanf("%d%d",&fir,&las);
        addedge(fir,las);
        addedge(las,fir);
        ednum[fir]++;
        ednum[las]++;
    }
    bfs();
    bfs2();
    printf("%d",ans[1] );
    for (int i = 2; i <= n; ++i)
    {
        printf(" %d",ans[i] );
    }
    printf("\n");

    return 0;
}

 

posted @ 2017-05-15 21:53  miamiao  阅读(285)  评论(0编辑  收藏  举报