貝殼找房在遙遠的傳奇境外,找到了一個強大的魔法師顧問。他有 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\n"); 98 else 99 printf("0\n"); 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\n",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\n",ans); 117 } 118 return 0; 119 }