题解报告——Financial Crisis

传送门

【思路分析】

 这道题是一道双连通分量的板子题,我们只需要套个双联通分量,在用并查集判断连通性。

如果两个点连通且不在一个双连通分量里,那么就只存在唯一路径,否则存在多条(值得注意的是如果一个双连通分量只有两个点,那么就GG了,要排除这种情况)。

【代码实现】

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<cctype>
  6 #include<stack>
  7 using namespace std;
  8 inline void read(int &gg)
  9 {
 10     char ch;int x,f;
 11     while(!isdigit(ch=getchar())&&ch!='-'); ch=='-'?(x=0,f=-1):(x=ch-'0',f=1);
 12     while(isdigit(ch=getchar())) x=x*10+ch-'0';
 13     gg=x*f;
 14 }
 15 const int maxn=5100;
 16 struct sd{
 17     int from,to;
 18 };
 19 vector<int> link[maxn],belong[maxn],bcc[maxn];
 20 stack<sd> stk;
 21 int dfn[maxn],low[maxn],bccno[maxn],fa[maxn],cnt,n,m,q,bccnt;
 22 int find(int v)
 23 {
 24     if(fa[v]!=v) fa[v]=find(fa[v]);
 25     return fa[v];
 26 }
 27 void tarjan(int v,int ff)
 28 {
 29     dfn[v]=low[v]=++cnt;
 30     for(int i=link[v].size()-1;i>=0;i--)
 31     {
 32         int to=link[v][i];
 33         if(to==ff) continue;
 34         sd edge=(sd){v,to};
 35         if(!dfn[to])
 36         {
 37             stk.push(edge);
 38             tarjan(to,v);
 39             low[v]=min(low[v],low[to]);
 40             if(low[to]>=dfn[v])
 41             {
 42                 bcc[++bccnt].clear();
 43                 while(1)
 44                 {
 45                     sd ee=stk.top();stk.pop();
 46                     int f=ee.from,tt=ee.to;
 47                     if(bccno[f]!=bccnt)
 48                     bccno[f]=bccnt,bcc[bccnt].push_back(f),belong[f].push_back(bccnt);
 49                     if(bccno[tt]!=bccnt)
 50                     bccno[tt]=bccnt,bcc[bccnt].push_back(tt),belong[tt].push_back(bccnt);
 51                     if(f==v&&tt==to) break;
 52                 }
 53             }
 54         }
 55         else if(dfn[to]<dfn[v])
 56         {
 57             stk.push(edge);
 58             low[v]=min(low[v],dfn[to]);
 59         } 
 60     }
 61 }
 62 void remove()
 63 {
 64     cnt=bccnt=0;
 65     memset(dfn,0,sizeof(dfn));
 66     memset(low,0,sizeof(low));
 67     memset(bccno,0,sizeof(bccno));
 68     for(int i=0;i<n;i++) fa[i]=i,link[i].clear(),belong[i].clear();
 69 }
 70 int main()
 71 {
 72     int time=0;
 73     while(1)
 74     {
 75         read(n),read(m);read(q),remove();int a,b;
 76         if(n==0&&m==0&&q==0) break;
 77         for(int i=1;i<=m;i++)
 78         {
 79             read(a),read(b);
 80             link[a].push_back(b);
 81             link[b].push_back(a);
 82             int ffa=find(a),ffb=find(b);
 83             if(ffa!=ffb) fa[ffb]=ffa;
 84         }
 85         printf("Case %d:\n",++time);
 86         for(int i=1;i<=n;i++)
 87         if(!dfn[i]) tarjan(i,0);
 88         while(q--)
 89         {
 90             read(a),read(b);
 91             if(find(a)!=find(b)) {printf("zero\n");continue;}
 92             bool flag=0;
 93             for(int i=belong[a].size()-1;i>=0&&!flag;i--)
 94             for(int j=belong[b].size()-1;j>=0&&!flag;j--)
 95             {
 96                 if(belong[a][i]==belong[b][j]) 
 97                 if(bcc[belong[a][i]].size()>2) flag=1;
 98             }
 99             if(flag) printf("two or more\n");
100             else printf("one\n");
101         }
102     }
103     return 0;
104 }

猜你喜欢

转载自www.cnblogs.com/genius777/p/9169438.html