[題解/考試]國王飲水記
Posted superminivan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[題解/考試]國王飲水記相关的知识,希望对你有一定的参考价值。
前言:今日又考試了,一道斐波那契的入門題因為沒有特判0錯了一個點,兩道不會,結果連rk7、8都沒拿到,
前天把鉛筆盒丟掉了,裡面有筆,耳機和U盤。U盤裡有做過的題,一些模板,寒假講的東西和課件,6個遊戲,一些安裝包和一些網址。
發現丟掉以後就變得特別絕望,極度悲傷,可是這就是命運啊,你不接受那就去死好了。
人活著本來就沒有什麼意義可言,尋找意義自然也是不可能尋找到的了。
意義什麼的都是小孩子的事情,所以只能這樣活著了。
與其如此那還不如把U盤裡的東西裝到腦子裡,也不必擔心什麼了。
n個點,按順序有m條邊,每次詢問最大的最小生成森林的邊權和以及1號所在的聯通塊點數(包括自己)。
輸入:第一行n,m。 接下來m行,每條邊的u,v,w。
輸出:m行,每行 權值之和、1所在聯通塊的點數。
數據規模:60% n,m<=1000
100%n,m<=5000,1<=u,v<=n,u!=v,0<w<=10^5.
對於圖G=(V,E),選取E‘ 屬於E,不產生重邊和環,并使|E‘|最大,在這個前提下,使得總邊權最小,那麼G‘=(V,E‘)就是最大的最小生成森林。
要想拿到100分還不知道怎麼寫,不過對我來說60分的解法都不會......
60%思路:
每讀進來一條邊就可以用并查集亂搞,如果這兩點沒有聯通,那麼直接連上就行,sum加一下w就行
如果已經聯通,那麼這條邊就有可能更新sum值,這裡可以每次都跑一次最小生成樹,重置sum再把選中的邊加上,但是複雜度有點高。
dalao的代碼:(我的還沒改出來)
#include<iostream> #include<cstdio> #include<algorithm> #define R register int using namespace std; struct edge { int u,v,w; bool operator < (const edge& y)const{return w<y.w;} }e[5001],tmp[5001]; int n,m,f[5001],s[5001],cnt=1,ans,cntw,lst; inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==‘-‘?-1:fix; do ret=(ret<<1)+(ret<<3)+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline void init(int k) { for(R i=1;i<=k;i++) f[i]=i,s[i]=1; } int getf(int x) { return x==f[x]?x:f[x]=getf(f[x]); } inline bool merge(int u,int v) { R uf=getf(u),vf=getf(v); if(uf==vf) return true; else { if(uf==1) { f[vf]=uf; s[uf]+=s[vf]; } else if(vf==1) { f[uf]=vf; s[vf]+=s[uf]; } else { f[vf]=uf; s[uf]+=s[vf]; }return false;} } // inline void kruskal(int k){ // for(R i=lst+1;i<=k;i++) tmp[i].u=e[i].u,tmp[i].v=e[i].v,tmp[i].w=e[i].w; ans=0; // sort(tmp+1,tmp+k+1); init(k); // for(R i=1;i<=k;i++){ // if(!merge(tmp[i].u,tmp[i].v)) ans+=tmp[i].w; // } // } namespace krusk{ int fa[5001]; inline void init(int k) {for(R i=1;i<=k;i++) fa[i]=i;} int getf(int x) { return x==fa[x]?x:fa[x]=getf(fa[x]); } inline bool merge(int u,int v) { R uf=getf(u),vf=getf(v); if(uf==vf) return true; else {fa[vf]=uf; return false;} } inline void kruskal(int k){ for(R i=lst+1;i<=k;i++) tmp[i].u=e[i].u,tmp[i].v=e[i].v,tmp[i].w=e[i].w; ans=0; sort(tmp+1,tmp+k+1); init(n); for(R i=1;i<=k;i++){ if(!merge(tmp[i].u,tmp[i].v)) ans+=tmp[i].w; } } } signed main() { n=g(),m=g(); for(R i=1;i<=n;i++) f[i]=i,s[i]=1; for(R i=1;i<=m;i++) e[i].u=g(),e[i].v=g(),e[i].w=g(); for(R i=1;i<=m;i++) { R u=e[i].u,v=e[i].v,w=e[i].w; if(merge(u,v)) { krusk::kruskal(i); cntw=min(cntw,ans); } else { cntw+=w; } printf("%d %d ",cntw,s[1]); } return 0; }
以後可能會更新的吧
以上是关于[題解/考試]國王飲水記的主要内容,如果未能解决你的问题,请参考以下文章