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("-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 }
View Code

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM