问题链接
题目大意:
给你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好像有聚聚用缩点写的,主要是处理环
*/