uoj49四驅兄弟(最小生成樹)

Description
如果你和萌蛋一樣,也看過《四驅兄弟》,你或許會記得,有一局比賽十分特別,只按照55個人中的第44名計算成績。

現在我們將問題擴展一下: 一共有nn個隊員, 只按照其中的第kk名計算成績。而賽車的規則也有所不同:一共有mm個賽車,每個賽車裝配着22個 GP 晶片的終端,且第ii個賽車預期到達終點的時間爲aiai。(注:不同賽車上的終端可以對應着相同的GP晶片,但不會22個都相同;任何賽車上的22個終端對應的 GP 晶片都是不同的)

比賽開始時,nn個隊員依次選擇自己的賽車。對於每個隊員, 他可以選擇開啓 GP 晶片功能或不開啓。如果開啓,那麼22個終端對應的 GP 晶片就會建立連接, 且這個賽車的比賽用時就是預期時間aiai; 如果不開啓, 那麼 GP 晶片不會建立連接,但是這個賽車的比賽用時將會非常長(可以認爲是無窮)。 甚至,他可以放棄比賽,這樣他不會佔用任何賽車,但是當然比賽用時也會被認爲是無窮。

任何時候,一旦存在若干個(至少33個)晶片A,B,C,...,XA,B,C,...,X滿足:AA與BB建立了連接,BB與CC建立了連接, ……,XX與AA建立了連接(即形成了循環連接的情況), 那麼處理系統就會崩潰。 這是非常可怕的,我們寧可讓比賽用時變爲無窮也不能讓系統崩潰。

現在給出隊員和賽車的信息, 請輸出最優情況下的成績( 即第kk小的比賽時間的最小值)。 爲了增大難度,kk並不是給出的,而是你需要對於1≤k≤n1≤k≤n的所有的kk輸出答案

輸入
第一行爲兩個整數n,mn,m。

接下來mm行,每行描述了一個賽車, 格式爲空格隔開的一個整數和兩個字符串, 分別是aiai和它的兩個終端對應的 GP 晶片名。

輸出
nn行,每行一個整數, 第ii行表示i=ki=k時的答案。 特別地,如果答案是無窮,輸出INF。

樣例
[input]
3 3
95 GP_1 GP_2
100 GP_1 gp@3
100 gp@3 GP_2

[output]
95
100
INF

樣例解釋
以下是一種最優方案(方案可能不唯一):

首先,33人各自選擇了11輛賽車。(都沒有放棄參賽)

如果k=1k=1, 那麼讓賽車11開啓 GP 晶片,其餘不開啓, 此時33個賽車的比賽時間分別爲95,INF,INF,95,INF,INF,第11名的成績是9595。

如果k=2k=2, 那麼讓賽車22和33開啓 GP 晶片, 而賽車11不開啓,此時33個賽車的比賽時間分別爲100,100,INF,100,100,INF,第22名的成績是100100。

如果k=3k=3, 那麼由於33輛賽車不可能都開啓 GP 晶片( 因爲假設都開啓,那麼 3 個 GP 晶片會出現循環連接的情況, 這是不允許的), 所以總有賽車沒有開啓 GP 晶片,那麼第33名的成績一定是INFINF。

數據
對於 20%的數據,n,m≤3n,m≤3, GP 晶片名稱的長度均爲11。
對於 40%的數據,n,m≤6n,m≤6, GP 晶片名稱的長度均爲11。
對於 60%的數據,n,m≤1,000n,m≤1,000, GP 晶片的長度不會超過33。
對於 100%的數據,0<n,m≤100,000,0<ai≤1,000,000,0000<n,m≤100,000,0<ai≤1,000,000,000, GP 晶片的名稱只包含大小寫字母、 數字、 “@” 、 “_”共6464種字符且長度不會超過 5且非空。

時間限制: 1秒


【思路】以車爲邊,字符串爲點,建立最小生成樹,邊權從小到大即爲1~k的值,其餘的用INF補足。

【代碼】

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define maxn 1000006
using namespace std;
map<string,int>mp;
struct data{
    int u,v,w;
    bool operator <(const data &b)const{
        return (w<b.w);
	}
}e[maxn];
int n,m,cnt=0,k=0,fa[maxn];
string s1,s2;
int getfa(int x){
    if(fa[x]==x)return fa[x];
    else return fa[x]=getfa(fa[x]);
}
int get(){
    char c;while(!isdigit(c=getchar()));
    int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
    return v;
}
void init(){
    n=get();m=get();
    for(int i=1;i<=m;++i){
        e[i].w=get();cin>>s1;cin>>s2;
        if(!mp.count(s1))mp[s1]=++cnt;
        if(!mp.count(s2))mp[s2]=++cnt;
        e[i].u=mp[s1];
        e[i].v=mp[s2];
	}
	for(int i=1;i<=cnt;++i)fa[i]=i;
	sort(e+1,e+1+m);k=n;
	for(int i=1;i<=m;++i){
	    int x=getfa(e[i].u),y=getfa(e[i].v);
	    if(x!=y){
	        fa[x]=y;
	        --k;
	        printf("%d\n",e[i].w);
	        if(k==1)break;
		}
	}
	while(k)printf("INF\n"),--k;
}
int main(){
    init();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章