2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)
Posted hk lin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)相关的知识,希望对你有一定的参考价值。
贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问。他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色。为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 10^5105 的字符串。现在魔法师想要通过一系列魔法使得这两个字符串相同。每种魔法形如 (u, v), u, v le 10^5(u, v), u, v≤105,可以将一个字符 uu改成一个字符 vv,并且可以使用无限次。出于种种原因,魔法师会强行指定这两个串能否进行修改。
若失败输出 -1?1,否则输出最少使用的魔法的种类数。
输入格式
一个正整数 n(n le 10^5)n(n≤105) 表示每个字符串的长度。
接下来两行每行首先输入一个单词("Variable"
或"Constant"
),"Variable"
表示这个字符串能进行修改,"Constant"
表示这个字符串不能进行修改,然后 nn 个正整数表示一个字符集不大于 10^5105 的字符串。
输出格式
若有解,输出一个自然数表示最少使用的魔法的种类数。否则输出 -1?1。
保证所有输入的数字都为正整数且不大于 10^5105。
样例输入1
2 Constant 111 222 Variable 222 111
样例输出1
2
样例输入2
2 Variable 111 222 Variable 222 111
样例输出2
1
题目来源
不说了 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("-1 "); 98 else 99 printf("0 "); 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("%d ",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("%d ",ans); 117 } 118 return 0; 119 }
以上是关于2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)的主要内容,如果未能解决你的问题,请参考以下文章