題目:
吉兒是一家古董店的老闆娘,由於她經營有道,小店開得紅紅火火。昨天,吉兒無意之中得到了散落民間幾百年的珍寶—月亮之眼。吉兒深知「月亮之眼」價值連城:它是由許多珍珠相連而成的,工匠們用金線連線珍珠,每根金線連線兩個珍珠;同時又對每根金線染上兩種顏色,一半染成銀白色,一半染成黛黑色。由於吉兒自小熟讀古籍,所以還曉得「月亮之眼」的神秘傳說:「月亮之眼」原是乙個古代寺廟的寶物,原本是掛在佛堂的一根頂梁柱上的,整個寶物垂直懸掛,所有珍珠排成一線,且都鑲嵌在柱子裡,而每一根金線又都是繃緊的,並且金線的銀白色一端始終在黛黑色一端的上方;然而,在乙個月圓之夜,「月亮之眼」突然從柱裡飛出,掉落下來,寶物本身完好無損,只是僧侶們再也無法以原樣把「月亮之眼」嵌入柱子中了。吉兒望著這個神秘的寶物,回憶著童年讀到的傳說,頓時萌發出恢復「月亮之眼」的衝動,但是擺弄了幾天依舊沒有成功。
現在,要麻煩您來幫助吉兒完成這項使命。
您要設計乙個程式,對於給定的「月亮之眼」進行周密分析,然後給出這串寶物幾百年前嵌在佛堂頂梁柱上的排列模樣。給定的「月亮之眼」有n個珍珠和p根金線,所有珍珠按一定順序有了乙個序號:1、2…、n。
輸入資料報含乙個「月亮之眼」的特徵描述:
檔案第一行有兩個整數n和p,其中n表示寶物中的珍珠個數,p表示寶物中的金線根數;
以下p行描述珍珠連線情況:
檔案第i+1行有三個整數,ri1,ri2,li。其中ri1表示第i根金線的銀白色一端連線的珍珠序號;ri2表示第i根金線的黛黑色一端連線的珍珠序號;li表示第i根金線的長度。
由於珍珠尺寸很小,所以幾個珍珠可以同時鑲嵌在乙個位置上。
您的輸出資料描述的是「月亮之眼」各個珍珠在頂梁柱上的位置,輸出檔案共n行:
第i行,乙個整數s,它表示標號為i的珍珠在頂梁柱上距離最高位置珍珠的距離。
注意:若無解則輸出僅一行,包含乙個整數「-1」。
9 9
1 2 3
2 3 5
2 7 1
4 5 4
5 6 1
5 9 1
6 7 1
7 8 3
9 8 4
2510
0456
95
1s
n,p<=500
balkan oi 1998
思路:
並查集,連線兩個珠子就把它們所在的子樹合併。fa儲存祖先節點,d儲存到祖先節點的距離。
關於判斷是否可行:連線兩個節點時,如果兩個節點x、y在同一棵樹上且 d[x]+z!=d[y](z為線的長度),則不可行。因為如果d[x]+zd[y] 時線繃不緊。
關於合併兩點:兩節點有同乙個根節點就不用再連線了(只需判斷是否能連線而不需要真的合併)。若連線根節點不同的兩節點x、y(x在上),按照並查集的做法就該連線此兩點的根節點。而連線根節點是有幾種情況:
1、rootx比rooty高
此時,應將rooty連在rootx上且線長為d[x]-d[y]+z。
2、rooty比rootx高
在這種情況下,應將rootx連線在rooty上且線長為d[y]-d[x]-z。
綜上:
if(d[x]-d[y]+z>=0)
if(d[x]-d[y]+z<0)
因為只能低的節點指向高的節點,所以不能寫abs(d[x]-d[y]+z)。
關於find函式中的更新方法:
int find(int x)
關於輸出:
注意,輸出前要把所有的點都find一下。
**:
#include#include#includeusing namespace std;
int n,m;
int d[510]= ,fa[510]= ;
int find(int x)
int main()
if(d[x]-d[y]+z<0)
} else
} }for(int i=1; i<=n; i++)
return 0;
}
裝箱問題 vijos
有乙個箱子容量為v 正整數,o v 20000 同時有n個物品 o n 30 每個物品有乙個體積 正整數 要求從 n 個物品中,任取若千個裝入箱內,使箱子的剩餘空間為最小。第一行,乙個整數,表示箱子容量 第二行,乙個整數,表示有n個物品 接下來n行,分別表示這n個物品的各自體積。乙個整數,表示箱子剩...
vijos 積木城堡
恰似今天更了七章 我該怎麼辦 看上去好像只能瘋狂寫揹包啦 他們說周四化學通練,我好慌 描述 第一行是乙個整數n n 100 表示一共有幾座城堡。以下n行每行是一系列非負整數,用乙個空格分隔,按從下往上的順序依次給出一座城堡中所有積木的稜長。用 1結束。一座城堡中的積木不超過100塊,每塊積木的稜長不...
Vijos 河蟹王國
河蟹王國有一位河蟹國王,他的名字叫羊駝。河蟹王國富饒安定,人們和諧相處。有一天,羊駝國王心血來潮,想在一部分人中挑出最和諧的人。於是,羊駝國王將他的子民排成了一列 b汗 好長呀 每個人都有乙個初始的和諧值。羊駝國王每次會選擇乙個區間 l,r 這個區間中和諧值最大的人就是國王選出的人。而且,在某一時間...