日常训练20161018 证据
2016-10-18 16:14
211 查看
有一幅n个点,m条边的无向图,取一些边使得图是一个由k棵树构成的森林并且分数最大。分数定义为边权积,但图中有若干坏点,坏点所在联通块的边权不计入内。求最大分数。若无方案输出-1。
贪心的思想,一开始先连好点之间的边,再连坏点之间的边,若还需要继续连边,则必须连好点与坏点之间的边,会损失一些权值,每次挑最小损失的联通块连到坏点即可。(比损失的时候对乘积取log就能比较大小了)
贪心的思想,一开始先连好点之间的边,再连坏点之间的边,若还需要继续连边,则必须连好点与坏点之间的边,会损失一些权值,每次挑最小损失的联通块连到坏点即可。(比损失的时候对乘积取log就能比较大小了)
type rec=record v:extended; i:longint; end; const p=1000000007; var heap:array[0..200050] of rec; fact,x,y,z,fa,flag,chs:array[0..200050] of longint; tot:array[0..200050] of extended; n,m,k,i,cnt:longint; ans:int64; t:rec; procedure swap(var a,b:longint); var t:longint; begin t:=a;a:=b;b:=t;end; procedure sort(l,r:longint); var i,j,e:longint; begin i:=l;j:=r;e:=z[(l+r)>>1]; repeat while z[i]>e do inc(i); while e>z[j] do dec(j); if not (i>j) then begin swap(x[i],x[j]); swap(y[i],y[j]); swap(z[i],z[j]); inc(i);dec(j); end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; function find(x:longint):longint; begin if fa[x]=x then exit(x); fa[x]:=find(fa[x]); exit(fa[x]); end; procedure choose_useful; var i,f1,f2:longint; begin for i:=1 to m do begin if (fact[x[i]]=0) or (fact[y[i]]=0) then continue; f1:=find(x[i]); f2:=find(y[i]); if (k>0)and(f1<>f2) then begin dec(k); fa[f1]:=f2; tot[f2]:=tot[f1]+tot[f2]+ln(z[i]); chs[i]:=1; if (k=0) then exit; end; end; end; procedure choose_useless; var i,f1,f2:longint; begin for i:=1 to m do begin if (fact[x[i]]=1) or (fact[y[i]]=1) then continue; f1:=find(x[i]); f2:=find(y[i]); if (k>0)and(f1<>f2) then begin dec(k); fa[f1]:=f2; if (k=0) then exit; end; end; end; procedure heap_up(x:longint); var t:rec; begin while (x>1)and(heap[x].v<heap[x>>1].v) do begin t:=heap[x];heap[x]:=heap[x>>1];heap[x>>1]:=t; x:=x>>1; end; end; procedure heap_down(x:longint); var t:rec; e:longint; begin while (x<<1<=cnt)and(heap[x].v>heap[x<<1].v)or(x<<1+1<=cnt)and(heap[x].v>heap[x<<1+1].v) do begin if (x<<1+1<=cnt)and(heap[x<<1+1].v<heap[x<<1].v) then e:=x<<1+1 else e:=x<<1; t:=heap[x];heap[x]:=heap[e];heap[e]:=t; x:=e; end; end; procedure push(t:rec); begin inc(cnt); heap[cnt]:=t; heap_up(cnt); end; function poop:rec; begin poop:=heap[1]; heap[1]:=heap[cnt]; dec(cnt); heap_down(1); end; procedure print(x:longint); begin writeln(x); close(input);close(output); halt; end; begin assign(input,'evidence.in');reset(input); assign(output,'evidence.out');rewrite(output); read(n,m,k);k:=n-k; for i:=1 to n do read(fact[i]); for i:=1 to m do read(x[i],y[i],z[i]); for i:=1 to n do fa[i]:=i; sort(1,m); if (k>0) then choose_useful; if (k>0) then choose_useless; for i:=1 to m do if (fact[x[i]]<>fact[y[i]]) then begin if (fact[y[i]]=1) then swap(x[i],y[i]); flag[find(x[i])]:=1; end; for i:=1 to n do if (flag[i]=1) then begin t.v:=tot[i]; t.i:=i; push(t); end; while (cnt>0)and(k>0) do begin t:=poop; flag[t.i]:=2; dec(k); end; if (k>0) then print(-1); ans:=1; for i:=1 to m do if (chs[i]=1)and(flag[find(x[i])]<2) then ans:=ans * z[i] mod p; print(ans); end.
相关文章推荐
- 日常训练20161018 subset
- 日常训练 20170531 探险
- 日常训练 20170605 MediumProblem
- HEU日常训练10.02
- [日常训练] God Knows
- 日常训练 20170620 技能树skill
- BNU 0919 日常训练 之 G N! ——高精度 万进制 10000的阶乘
- 日常训练 矩阵
- 日常基本功训练方法及要求与标准。
- 日常训练 20170606 魔法手镯
- [日常训练] Lost My Music
- 日常训练20161031 量化交易 trade
- 日常训练
- 日常训练 平均数
- Codeforces Round #423 (Div. 2)A-B-C-D 日常训练打卡
- 日常训练 20170606 极地旅行社
- [日常训练] 藏宝路径
- [日常训练] 魔法传输
- [日常训练] 三角形
- 周六日常训练,背包dp,树形dp,简单dp以及很多数学?