天天看點

曆屆試題 國王的煩惱 (藍橋杯)

   問題描述   C國由n個小島組成,為了友善小島之間聯絡,C國在小島間建立了m座大橋,每座大橋連接配接兩座小島。兩個小島間可能存在多座橋連接配接。然而,由于海水沖刷,有一些大橋面臨着不能使用的危險。

  如果兩個小島間的所有大橋都不能使用,則這兩座小島就不能直接到達了。然而,隻要這兩座小島的居民能通過其他的橋或者其他的小島互相到達,他們就會安然無事。但是,如果前一天兩個小島之間還有方法可以到達,後一天卻不能到達了,居民們就會一起抗議。

  現在C國的國王已經知道了每座橋能使用的天數,超過這個天數就不能使用了。現在他想知道居民們會有多少天進行抗議。 輸入格式   輸入的第一行包含兩個整數n, m,分别表示小島的個數和橋的數量。

  接下來m行,每行三個整數a, b, t,分别表示該座橋連接配接a号和b号兩個小島,能使用t天。小島的編号從1開始遞增。 輸出格式   輸出一個整數,表示居民們會抗議的天數。 樣例輸入 4 4

1 2 2

1 3 2

2 3 1

3 4 3 樣例輸出 2 樣例說明   第一天後2和3之間的橋不能使用,不影響。

  第二天後1和2之間,以及1和3之間的橋不能使用,居民們會抗議。

  第三天後3和4之間的橋不能使用,居民們會抗議。 資料規模和約定   對于30%的資料,1<=n<=20,1<=m<=100;

  對于50%的資料,1<=n<=500,1<=m<=10000;

  對于100%的資料,1<=n<=10000,1<=m<=100000,1<=a, b<=n, 1<=t<=100000。

 剛看到這題就想着用暴力。。資料太大,也就沒嘗試。第一次确實想到并查集,但是我了解的和之前有用過的并查集太單一,沒有說類似的題目。也就放棄了。百度!

曆屆試題 國王的煩惱 (藍橋杯)

隻要百度一下,後面全部跟着(并查集),我當時也沒打開看,我想着自己做試試,是真想不到,因為我一用并查集有好多路徑都給覆寫掉了,很多點都會遺漏。 看了好多大佬的部落格,才想到。

思路就是根據天數從大到小排序,從大到小開始周遊,如果某個橋的兩端不是連通的,他們就會抗議。因為天數更小的即使使這兩端連通,因為天數較小,過了幾天後,他們還是不連通。(要注意判斷天數相同的情況) 例如例題給的案例 4 4

1 2 2

1 3 2

2 3 1

3 4 3

曆屆試題 國王的煩惱 (藍橋杯)

排序後變成 3,4,3 1,2,2 1,3,2 2,3,1 依次周遊從第一個開始 因為本身3,4并不連通,是以抗議sum++; 同理1,2也不連通,sum++; 到1,3的時候,1,3也是不連通的,也要抗議,但是因為提議說是抗議幾天,1,2和1,3的橋都是第二天壞,是以他們是同一天抗議,sum不變 最後到2,3,  這兩點是連通的,是以sum保持不變,

還有點。之前沒注意過 我的  find函數是 while(a[x]!=x) x=a[x];  return x; 但是如果這樣送出是逾時的,隻有80分 參考了大佬的代碼他們的find函數是 if (a[x]==x)  return x;

 return a[x]=find(a[x]);

。。差距

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct node{
	int x,y,day;
}node;
int a[10000+10]={0};
bool cmp(node n1,node n2){
	return n1.day>n2.day;
}
int find(int x){//切記
	if (a[x]==x)
        return x;
    return a[x]=find(a[x]);
}
int add(int x,int y){
	x=find(x);
	y=find(y);
	if(x!=y){
		a[x]=y;
		return 1;
	}
	return 0;
}
int main(){
	node s[100000+10];
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		cin>>s[i].x>>s[i].y>>s[i].day;
	}
	for(int i=1;i<=n;i++)
	a[i]=i;
	sort(s,s+m,cmp);
	int p=-1,sum=0;//p代表前一天抗議的時間
	for(int i=0;i<m;i++){
		int pd=add(s[i].x,s[i].y);
		if(pd&&p!=s[i].day){//今天的天數不能和上次抗議的天數相同,類似于橋1,2和橋1,3
			sum++;
			p=s[i].day;
		}
	}
	cout<<sum;
	return 0;
}
           

這題挺有收獲的,之前認識的并查集太片面....

歡迎大家加入 早起學習群,一起學習一起進步!(群号: 642179511 )

繼續閱讀