USACO4.3 Street Race【分析】

这道题,感觉不是很难,分析清楚之后非常简单。(标签都不知道怎么加)

读完题首先想到了分割点一定是必经点的一种特殊情况,如果分割点不是必经点的话,那么它就不能把这个图分成两半(存在不经过它的边沟通两半)

然后先做比较简单的必经点。想到了割点,但是数据规模太小了,所以不用那么复杂,直接暴力枚举尝试把除起点终点之外的所有点全部删掉,判断图是否连通就可以了。

在必经点的基础上做分割点。

删掉一个点之后,从$0$号点出发标记所有能够遍历到的点,再从被删掉的那个点出发,如果碰到了之前遍历过的点就说明这个点不是分割点。

要注意一个特殊情况:如果这个节点有自环,那么这个节点就不能当做分割点。(自环的那条边为两部分的公共边)(代码里写得很丑,现在想来直接特判一下不就可以了吗)

实现不是很难,广搜和深搜都可以。

(代码里编号好像忘了排序,数据好水啊)

  1 //nice
  2 /*
  3 ID: Starry21
  4 LANG: C++
  5 TASK: race3               
  6 */ 
  7 #include<cstdio>
  8 #include<algorithm>
  9 #include<vector>
 10 #include<cstring>
 11 #include<queue>
 12 using namespace std;
 13 #define N 55
 14 #define ll long long
 15 #define INF 0x3f3f3f3f
 16 int n;
 17 vector<int>G[N],ans1,ans2;
 18 int vis[N];
 19 queue<int>Q;
 20 int main() 
 21 {
 22     //freopen("race3.in","r",stdin);
 23     //freopen("race3.out","w",stdout);
 24     while(1)
 25     {
 26         int x;
 27         while(scanf("%d",&x)!=EOF)
 28         {
 29             if(x==-2||x==-1) break;
 30             G[n].push_back(x);
 31         }
 32         if(x==-1) break;
 33         n++;
 34     }
 35     n--;
 36     //printf("%d\n",n);
 37     /*for(int i=0;i<=n;i++)
 38     {
 39         for(int j=0;j<G[i].size();j++)
 40             printf("%d ",G[i][j]);
 41         puts("");
 42     }*/
 43     for(int s=1;s<=n-1;s++)//0是起点 n是终点 枚举必经点
 44     {
 45         memset(vis,0,sizeof(vis));
 46         while(!Q.empty()) Q.pop();
 47         Q.push(0);
 48         vis[0]=1;
 49         while(!Q.empty())
 50         {
 51             int u=Q.front();Q.pop();
 52             for(int i=0;i<G[u].size();i++)
 53             {
 54                 int v=G[u][i];
 55                 if(vis[v]) continue;
 56                 vis[v]=1;//56 57行顺序 防自环 
 57                 if(v==s) continue;
 58                 Q.push(v);
 59             }
 60         }
 61         if(vis[n]) continue;
 62         //vis[i]=1 是从0出发不经过s能够到达的点 
 63         ans1.push_back(s);
 64         bool f=0;
 65         while(!Q.empty()) Q.pop();
 66         Q.push(s);
 67         //这里vis[s]不赋值 防自环 
 68         while(!Q.empty())
 69         {
 70             int u=Q.front();Q.pop();
 71             for(int i=0;i<G[u].size();i++)
 72             {
 73                 int v=G[u][i];
 74                 if(vis[v]==2) continue;
 75                 if(v==s) continue;//vis[s]没有赋值2 
 76                 if(vis[v]==1)//访问到了从s也能到的点
 77                 {
 78                     f=1;
 79                     break;
 80                 } 
 81                 vis[v]=2;
 82                 Q.push(v);
 83             }
 84             if(f) break;
 85         }
 86         if(!f) ans2.push_back(s);
 87     }
 88     printf("%d",ans1.size());
 89     for(int i=0;i<ans1.size();i++)
 90         printf(" %d",ans1[i]);
 91     puts("");
 92     printf("%d",ans2.size());
 93     for(int i=0;i<ans2.size();i++)
 94         printf(" %d",ans2[i]);
 95     puts("");
 96 }
 97 /*
 98 注意自环的情况
 99 比如:
100 1 -2
101 2 1 -2
102 3 0 -2
103 3 4 -2
104 5 0 -2
105 7 6 -2
106 7 -2
107 8 -2
108 -2
109 -1
110 中的1号点 
111 */
Code

猜你喜欢

转载自www.cnblogs.com/lyttt/p/11809183.html