• 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);
     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
  • 相关阅读:
    读者试读怎么评价这本书
    性能优化是数据库应用的核心问题
    ExtJS 4 Grid组件
    发挥你的SATA硬盘
    MOSS 修改了服务器账号密码后的问题
    速度真快,ExtJS第5个预览版发布
    Ext JS 4 Preview Release 4发布
    显卡性能排行榜
    手机操作系统发展史
    程序解读身份证的密码
  • 原文地址:https://www.cnblogs.com/lyttt/p/11809183.html
Copyright © 2020-2023  润新知