Codeforces Gym 102501 K. Birdwatching(bfs)

问题链接

题目大意:

给你n个点,m条有向边和一个终止点st,问你对于任意一点u,u到st点距离为1且u到st点路径只有一条,那么这个点u符合条件,求出所有满足条件的点u

思路

在图中,多起点单一终点的情况下,一般采用反向建图
1.求出可能满足条件的所有点(距离st点的距离为1)
先把满足条件1的点存起来
2. 在满足条件1的前提下,集合中的点 要满足 到st的路径有且只有一条
设满足条件1的集合为s

反向建图后,问题转化为 从st点为起点到与他距离为1的点的路径只有一条

先从集合s中取出任意一点u,从u点开始bfs,如果能够bfs到集合s中的任意一点v,那么st到v点路径就会有两条,一条是st-v另一条是st-u-v ,所以v点是不满足条件的点,

还有一个地方需要考虑就是u点开始bfs之后又重新回到u点。也就是成环,那么按照上面点思路,我们会把u点 判定为不满足条件,这时候我们只需要bfs时记录当前点和起始点就可以了


Code


#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <vector>


using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 7;
const ll mod = 1000000007;

#define mst(x, a) memset( x,a,sizeof(x) )
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)

ll read() {
    
    
    ll x = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar();
    while(ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return x;
}

void out(ll x) {
    
    
    int stackk[40];
    if (x < 0) {
    
    
        putchar('-');
        x = -x;
    }
    if (!x) {
    
    
        putchar('0');
        return;
    }
    int top = 0;
    while (x) stackk[++top] = x % 10, x /= 10;
    while (top) putchar(stackk[top--] + '0');
}
int n,m,head[maxn],cnt,st,s[maxn],res,vis[maxn],fa[maxn];
vector<int>ans;
struct node {
    
    
    int  u,v,next;
} a[maxn];
void add(int u,int v) {
    
    
   a[cnt].u=u,a[cnt].v=v;
   a[cnt].next=head[u],head[u]=cnt++;
}
void bfs(){
    
    
    queue<PII>q;
    for(int i=1 ;i<=res ;i++) q.push({
    
    s[i],s[i]}),fa[s[i]]=s[i],vis[s[i]]=1;
    while(q.size()){
    
    
        PII fr =q.front();
        q.pop();
        int u=fr.first;
        int p=fr.second;
        for(int i=head[u];~i;i=a[i].next){
    
    
                int v=a[i].v;
                if(p==v) continue;
                if(vis[v]==0)
                {
    
    
                    q.push({
    
    v,p});
                    vis[v]=1;
                    fa[v]=p;
                }
                else  if(vis[v]==1)
                {
    
    
                    if(fa[v]!=p)  vis[v]++;
                    q.push({
    
    v,p});
                }
        }
    }
}
int main() {
    
    
    n=read(),m=read(),st=read();
    st++;
    mst(head,-1);
    for(int i=1 ;i<=m ;i++)
    {
    
    
        int u=read();
        u++;
        int v=read();
        v++;
        if(v==st)
        {
    
    
            s[++res]=u;
            continue;
        }
        add(v,u);
    }
    bfs();
    for(int i=1 ;i<=res ;i++) if(vis[s[i]]==1) ans.push_back(s[i]);
    sort(ans.begin(),ans.end());
    out(ans.size());
    puts("");
    for(int i:ans)
    {
    
    
        out(--i);
        puts("");
    }
    return 0;
}
/*

upc好像有聚聚用缩点写的,主要是处理环
*/

猜你喜欢

转载自blog.csdn.net/wmy0536/article/details/109478719