(File IO): input:wormsort.in output:wormsort.out
時間限制: 1000 ms 空間限制: 262144 KB 具體限制
Goto ProblemSet
題目描述
的奶牛們已經厭倦了他對她們每天早上排好序離開牛棚的要求。她們剛剛完成了量子物理學的博士學位,準備將這一過程搞快點。
今天早上,如同往常一樣, 的 頭編號爲 (1≤N≤10^5)$,分散在牛棚中 個編號爲 的不同位置,奶牛 位於位置 。但是今天早上還出現了 個編號爲 的蟲洞,其中蟲洞 i 雙向連接了位置 和 ,寬度爲 。
在任何時刻,兩頭位於一個蟲洞兩端的奶牛可以選擇通過蟲洞交換位置。奶牛們需要反覆進行這樣的交換,直到對於 ,奶牛 位於位置 。
奶牛們不想被蟲洞擠壞。幫助她們最大化被她們用來排序的蟲洞寬度的最小值。保證奶牛們有可能排好序。
輸入
輸入的第一行包含兩個整數 N 和 M。
第二行包含 個整數 。保證 是 的一個排列。
對於 到 之間的每一個 ,第 行包含整數 和 。
輸出
輸出一個整數,爲在排序過程中奶牛必須擠進的蟲洞的最小寬度的最大值。如果奶牛們不需要用任何蟲洞來排序,輸出 。
樣例輸入
4 4
3 2 1 4
1 2 9
1 3 7
2 3 10
2 4 3
樣例輸出
9
數據範圍限制
測試點 滿足 。
測試點 沒有額外限制。
提示
以下是一個僅用寬度至少爲 的蟲洞給奶牛排序的可能方案:
奶牛 和奶牛 使用第三個蟲洞交換位置。
奶牛 和奶牛 使用第一個蟲洞交換位置。
奶牛 和奶牛 使用第三個蟲洞交換位置。
解題思路
題意就是說有個蟲洞,在兩個地方傳送,現在問你讓所有的奶牛都到自己的地方所穿過的蟲洞寬度最小的最大值是多少。
抓住關鍵信息:
1.一個蟲洞如果確定了要經過,那麼就可以無限經過這個蟲洞。
2.當確定一個蟲洞要經過之後,寬度比他大的蟲洞都可以經過。
本題要用到並查集和一點小小的貪心,每次加入一條最大的邊,然後看看是否連通即可,因爲本題數據範圍較小,所以不需要啓發式合併,具體做法詳見代碼註釋。
代碼
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,a[100010],s,f[100010],xx,yy,ans;
struct c{//x,y 爲連接的兩個節點,z爲寬度
int x,y,z;
}b[100010];
bool cmp(const c&l,const c&r)
{
return l.z>r.z;
}
int find(int x)
{
if(f[x]==x)
return x;
return f[x]=find(f[x]);
}//並查集之 find
int main(){
freopen("wormsort.in","r",stdin);
freopen("wormsort.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z);
sort(b+1,b+m+1,cmp);
s=0,ans=-1;
for(int i=1;i<=n;i++) f[i]=i; //初始化,每個節點最初的“根”是自己
for(int i=1;i<=m;i++)
{
while(find(s)==find(a[s]))//判斷是否連通
{
s++;
if(s>=n-1)
{
printf("%d",ans);
return 0;
}
}
xx=find(b[i].x);
yy=find(b[i].y);
if(xx!=yy)//若不連通,則加入這條邊
{
f[xx]=yy;
ans=b[i].z;
}
}
printf("%d",ans);
}