CF1012B Chemical table 题解【二分图】【构造】
有意思的網格圖轉化。CF Div.1 還是挺有難度的。
注:由于本題有較完美的中文題面,所以不貼英文題面。
英文題面
題目描述
Innopolis 大學的教授正努力研究元素周期表。他們知道,有 \(n \times m\) 種元素,形成了一個 \(n\) 行 \(m\) 列的矩陣。
研究表明,如果元素周期表上有一個元素 A,且元素 B 與它在同一列(A 與 B 不能在同一周期),元素 C 在同一周期(A 與 C 不能在同一列),那么,科學家就可以用這三種元素通過核聚變合成第四種元素 D 的樣品,D 與 B 在同一周期,與 C 在同一列。
簡而言之,如果有在元素周期表中位置為 \((r_1, c_1),\ (r_1, c_2),\ (r_2, c_1)\) (其中 \(r_1\ne r_2,c_1\ne c_2\)?)的三種元素的樣品,就可以生成位置為 \((r_2, c_2)\)) 的樣品。如圖所示:
注意:在核聚變中被使用的樣品并不會消失,它們可以參與之后的反應;反應得到的樣品也可以參與反應。
他們已經獲得了 \(q\) 種元素的樣品。為了集齊所有元素的樣品,他們會購買一些樣品,然后利用核聚變制造出剩下元素的樣品。
請求出他們至少需要購買的元素樣品的數量。
輸入輸出格式
輸入格式:
第一行,\(3\) 個整數 \(n,m,q\ (1\le n,m\le 2\times 10^5, 0\le q\le\min \{n \times m, 2 \times 10^5\})\)。
之后的 \(q\) 行,每行 \(2\) 個整數 \(r_i, c_i\ (1\le r_i\le n,1\le c_i\le m)\)。保證給定的元素互不相同。
輸出格式:
輸出一個整數,表示至少需要購買的元素樣品的數量。
輸入輸出樣例
輸入樣例#1:
2 2 3 1 2 2 2 2 1輸出樣例#1:
0輸入樣例#2:
1 5 3 1 3 1 1 1 5輸出樣例#2:
2輸入樣例#3:
4 3 6 1 2 1 3 2 2 2 3 3 1 3 3輸出樣例#3:
1樣例解釋
說明
每個樣例解釋中有兩個矩陣。
第一個表示初始狀況(其中,打叉的是原本就有樣品的元素)。
第二個表示最終集齊樣品時的狀況(其中,藍圈代表核聚變得到的樣品,藍圈中的數字表示得到樣品的順序,紅圈表示購買的樣品)。
樣例解釋 1
通過給定的三種元素,可以得到第四種元素的樣品。
樣例解釋 2
由于給定的元素只有一行,無法使用核聚變,只能購買剩余的兩種元素的樣品。
樣例解釋 3
集齊所有元素的方法不唯一,以下是一種方法。其中,元素 \((4,2)\) 只有在購買元素 \((4,1)\) 的樣品,和反應得到元素 \((1,1)\) 的樣品后才能得到。
子任務
注意:當且僅當你通過了一個子任務下的所有測試點,你將獲得此子任務的分數。
| \(1\) | \(10\) | \(n=2\) | \(m=2\) | \(0\le q\le 4\) |
| \(2\) | \(17\) | \(1 \le n \le 2\) | \(1 \le m \le 20\) | \(0 \le q \le 20\) |
| \(3\) | \(8\) | \(1 \le n \le 20\) | \(1 \le m \le 20\) | \(q=0\) |
| \(4\) | \(20\) | \(1 \le n \le 20\) | \(1 \le m \le 20\) | \(0\le q \le 400\) |
| \(5\) | \(30\) | \(1 \le n \le 1 \times 10^4\) | \(1 \le m \le 1 \times 10^4\) | \(1 \le q \le 1 \times 10^5\) |
| \(6\) | \(15\) | \(1 \le n \le 2 \times 10^5\) | \(1 \le m \le 2 \times 10^5\) | \(1 \le q \le 2 \times 10^5\) |
題解:
一開始總在找規律,比如先放沒放過的行或列,先把給出的元素全部聚變一遍……
實際上在這個網格圖中,我們把每行、每列均抽象為一個點,可以看成是一個二分圖,每個點連接了它的行和列。
那么當一對行、列連通而它們之間又沒有直接連邊時,可以通過它的路徑生成同時在這一行且在這一列的那個點。因此不需要直接連邊。
那么我們計算把整個二分圖連通需要多少條邊,就是連通塊個數-1。
Code:
#include<cstdio> #include<cstring> struct edge {int n,nxt;edge(int n,int nxt){this->n=n;this->nxt=nxt;}edge(){} }e[400100]; int head[400100],ecnt=-1; void add(int from,int to) {e[++ecnt]=edge(to,head[from]);head[from]=ecnt;e[++ecnt]=edge(from,head[to]);head[to]=ecnt; } bool used[400100]; int dfs(int x) {used[x]=1;for(int i=head[x];~i;i=e[i].nxt)if(!used[e[i].n])dfs(e[i].n);return 1; } int main() {memset(head,-1,sizeof(head));int n,m,k,u,v;scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=k;++i){scanf("%d%d",&u,&v);add(u,n+v);}int ans=0;for(int i=1;i<=n+m;++i)if(!used[i])ans+=dfs(i);printf("%d\n",ans-1);return 0; }轉載于:https://www.cnblogs.com/wjyyy/p/cf1012b.html
總結
以上是生活随笔為你收集整理的CF1012B Chemical table 题解【二分图】【构造】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Thymeleaf相关补充
- 下一篇: 豁免保费是什么意思