題目描述 Description
lxhgww最近迷上了一款遊戲,在遊戲裏,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示.當他使用某種裝備時,他只能使用該裝備的某一個屬性.並且每種裝備最多隻能使用一次.
遊戲進行到最後,lxhgww遇到了終極boss,這個終極boss很奇怪,攻擊他的裝備所使用的屬性值必須從1開始連續遞增地攻擊,才能對boss產生傷害.也就是說一開始的時候,lxhgww只能使用某個屬性值爲1的裝備攻擊boss,然後只能使用某個屬性值爲2的裝備攻擊boss,然後只能使用某個屬性值爲3的裝備攻擊boss……以此類推
現在lxhgww想知道他最多能連續攻擊boss多少次?
輸入描述 Input Description
輸入的第一行是一個整數N,表示lxhgww擁有N種裝備
接下來N行,是對這N種裝備的描述,每行2個數字,表示第i種裝備的2個屬性值
輸出描述 Output Description
輸出一行,包括1個數字,表示lxhgww最多能連續攻擊的次數
樣例輸入 Sample Input
3
1 2
3 2
4 5
樣例輸出 Sample Output
2
數據範圍及提示 Data Size & Hint
對於 的數據,保證
對於 的數據,保證
Solution
這個題目有兩種方法都是可做的
- 二分圖匹配
這個就很顯然啦
直接將權值和點連邊,按順序刺激 的點看是否能形成增廣路,每個點最多刺激一次
- 並查集
剛開始知道能用並查集做我是懵逼的
看過HZWERdalao的博客後明白了
將[a,b]的一個物品看做連接[a,b]的一條邊
用並查集維護集合
若一個集合中能夠形成環,則說明集合中的數均可選
若一個集合中沒有環,僅僅爲一棵樹,則說明集合中有一個數選不了
當然我們將集合中最大的數設爲選不了就好了
最後從 按順序看每個點所處集合選不了的點是不是他本身即可
代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int point[N],fa[N],n;
int read() {
int ans=0,flag=1;
char ch=getchar();
while( (ch>'9' || ch<'0') && ch!='-' ) ch=getchar();
if(ch=='-') {flag=-1;ch=getchar();}
while(ch>='0' && ch<='9') {ans=ans*10+ch-'0';ch=getchar();}
return ans*flag;
}
int find(int x) {return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
int main() {
n=read();
for(int i=1;i<=10000;++i) point[i]=fa[i]=i;
for(int i=1;i<=n;++i) {
int x=read(),y=read();
int fx=find(x),fy=find(y);
if(fx==fy) point[fx]=0;
else {
point[fx]=max(point[fx],point[fy]);
fa[fy]=fx;
}
}
for(int i=1;i<=10000;++i) {
int fx=find(i);
if(point[fx]==i) {printf("%d\n",i-1);break;}
else if(i==10000) printf("%d\n",10000);
}
return 0;
}