Usaco Training Section 4.3 Street Race

题意真的挺绕的……

第一问求从起点到终点所有路径上哪些点肯定出现,其实也就是把这些点连的边删掉,起点就到不了终点,枚举一下,大概是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;
}

猜你喜欢

转载自blog.csdn.net/qq_36911709/article/details/82220803