题意真的挺绕的……
第一问求从起点到终点所有路径上哪些点肯定出现,其实也就是把这些点连的边删掉,起点就到不了终点,枚举一下,大概是O(nm)的。
第二问求有哪些个点能把图分成两块,两块之间没有共同的边,只有那个分割点是公共的。我们可以发现,第二问答案的集合属于第一问的集合,因为如果第一问的条件不满足,第二问的条件也不会满足。于是我们把第一问的答案每个作为分割点,每次跑两个dfs,第一个从起点出发,跑到分割点结束;第二个从分割点出发,只要经过第一个dfs到过的点,就不是答案。应该也是O(nm)的。
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 2147483647
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
struct edg{
int nxt,to;
}e[205];
int cnt,head[55];
int n=-1,tot,totb,a[55],b[55];
bool vis[55],vis2[55];
vector<int> gv[55];
bool f;
inline void add(int u,int v){
e[++cnt].nxt=head[u],head[u]=cnt,e[cnt].to=v;
}
inline void dfs(int u){
if(u==n){f=1;return;}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!vis[v]) vis[v]=1,dfs(v);
if(f) return;
}
}
inline void dfs2(int u,int j){
if(u==j) return;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!vis[v]) vis[v]=1,dfs2(v,j);
}
}
inline void dfs3(int u){
if(vis[u]){f=0;return;}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!vis2[v]) vis2[v]=1,dfs3(v);
if(!f) return;
}
}
int main()
{
freopen("race3.in","r",stdin);
freopen("race3.out","w",stdout);
while(1){
int x=read();
if(x==-1) break;
++n;
while(x!=-2) gv[n].pb(x),x=read();
}
for(int i=1;i<n;++i){
memset(head,0,sizeof(head));cnt=0;
for(int j=0;j<n;++j){
if(i==j) continue;
for(int k=0;k<(int)gv[j].size();++k){
int x=gv[j][k];
if(x==i) continue;
add(j,x);
}
}
f=0;
memset(vis,0,sizeof(vis));
vis[0]=1;
dfs(0);
if(!f) a[++tot]=i;
}
printf("%d",tot);
for(int i=1;i<=tot;++i) printf(" %d",a[i]);
puts("");
memset(head,0,sizeof(head));cnt=0;
for(int i=0;i<n;++i){
for(int k=0;k<(int)gv[i].size();++k){
int x=gv[i][k];
add(i,x);
}
}
for(int i2=1;i2<=tot;++i2){
int i=a[i2];
memset(vis,0,sizeof(vis));
vis[0]=1;
dfs2(0,i);
f=1;
vis[i]=0;
memset(vis2,0,sizeof(vis2));
vis2[i]=1;
dfs3(i);
if(f) b[++totb]=i;
}
printf("%d",totb);
for(int i=1;i<=totb;++i) printf(" %d",b[i]);
puts("");
return 0;
}