1. 程式人生 > >Usaco Training Section 4.3 Street Race

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;
}