2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问。他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色。为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 10^5105 的字符串。现在魔法师想要通过一系列魔法使得这两个字符串相同。每种魔法形如 (u, v), u, v le 10^5(u, v), u, v105,可以将一个字符 uu改成一个字符 vv,并且可以使用无限次。出于种种原因,魔法师会强行指定这两个串能否进行修改。

若失败输出 -11,否则输出最少使用的魔法的种类数。

输入格式

一个正整数 n(n le 10^5)n(n105) 表示每个字符串的长度。

接下来两行每行首先输入一个单词("Variable""Constant"),"Variable"表示这个字符串能进行修改,"Constant"表示这个字符串不能进行修改,然后 nn 个正整数表示一个字符集不大于 10^5105 的字符串。

输出格式

若有解,输出一个自然数表示最少使用的魔法的种类数。否则输出 -11。

保证所有输入的数字都为正整数且不大于 10^5105。

样例输入1

2
Constant 111 222
Variable 222 111

样例输出1

2

样例输入2

2
Variable 111 222
Variable 222 111

样例输出2

1
2018 计蒜之道 复赛 不说了 SB错误能卡我好久。对于cc的情况判字符串是不是相等。对于vv的情况并查集找联通块数,次数就是总点数减去联通块数。对于cv的情况我们仍旧双向存联通块。对于内部有自环的我们建的边数等于块内点数。对于没有自环的,我们建的边数等于块内点数-1。第二种情况跟vv的是类似的,第一种情况则是把所有点建成一个大的自环,这样所有点都互相可达了。
  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define INF 0x3f3f3f3f
  5 #define LL long long
  6 #define pb push_back
  7 #define mod 1000000007
  8 #define ls(i) (i<<1)
  9 #define rs(i) (i<<1|1)
 10 #define mp make_pair
 11 #define fi first
 12 #define se second
 13 using namespace std;
 14 const int N=1e5+10;
 15 const int P=1e5;
 16 int inf[2];
 17 int s[2][N];
 18 vector<int> e[N];
 19 bool vis[N],ins[N];
 20 bool ct[N];
 21 int fa[N];
 22 bool exist[N];
 23 int now,ans;
 24 char is[20];
 25 bool dfs(int u)
 26 {
 27     ins[u]=1;
 28     vis[u]=1;
 29     int flag=0;
 30     for(auto p:e[u])
 31     {
 32         if(ins[p])
 33         {
 34             flag=1;
 35             continue;
 36         }
 37         if(vis[p])
 38             continue;
 39         if(dfs(p)) flag=1;
 40     }
 41     ins[u]=0;
 42     return flag;
 43 }
 44 int Find(int x) {return fa[x]==x?x: fa[x]=Find(fa[x]);}
 45 void Union(int u,int v)
 46 {
 47     int x=Find(u),y=Find(v);
 48     if(x!=y)
 49         fa[x]=y;
 50     return ;
 51 }
 52 int main()
 53 {
 54     int n;
 55     scanf("%d",&n);
 56     for(int i=0;i<2;i++)
 57     {
 58         scanf("%s",is);
 59         if(strcmp(is,"Constant")==0)
 60             inf[i]=0;
 61         else
 62             inf[i]=1;
 63         for(int j=1;j<=n;j++)
 64             scanf("%d",&s[i][j]);
 65     }
 66     if(inf[0]==0)
 67         now=1;
 68     else
 69         now=0;
 70     int pt=inf[0]+inf[1];
 71     for(int i=1;i<=P;i++)
 72         fa[i]=i;
 73     for(int i=1;i<=n;i++)
 74     {
 75         if(pt>=1 && s[now][i]!=s[now^1][i])
 76             e[s[now][i]].pb(s[now^1][i]),Union(s[now][i],s[now^1][i]);
 77         exist[s[now][i]]=1;
 78         exist[s[now^1][i]]=1;
 79     }
 80     ans=0;
 81     for(int i=1;i<=P;i++)
 82     {
 83         if(e[i].size()>0)
 84         {
 85             sort(e[i].begin(),e[i].end());
 86             e[i].resize(unique(e[i].begin(),e[i].end())-e[i].begin());
 87         }
 88         if(exist[i]) ans++;
 89     }
 90     if(pt==0)
 91     {
 92         bool flag=0;
 93         for(int i=1;i<=n;i++)
 94             if(s[0][i]!=s[1][i])
 95                 flag=1;
 96         if(flag)
 97             printf("-1n");
 98         else
 99             printf("0n");
100     }
101     if(pt==1)
102     {
103         for(int i=1;i<=P;i++)
104             if(exist[i] && !vis[i])
105                 if(dfs(i)) ct[Find(i)]=1;
106         for(int i=1;i<=P;i++)
107             if(exist[i] && fa[i]==i && ct[i]==0)
108                 ans--;
109         printf("%dn",ans);
110     }
111     if(pt==2)
112     {
113         for(int i=1;i<=P;i++)
114             if(exist[i] && fa[i]==i)
115                 ans--;
116         printf("%dn",ans);
117     }
118     return 0;
119 }
View Code  

相关内容推荐