巨额奖金 Award

阅读: 评论:0

巨额奖金 Award

巨额奖金 Award

巨额奖金
Award/.IN/.OUT/.PAS/.EXE
问题描述
NJ 市的快速发展得益于其便捷的交通。可是,随着经济的发展,大量的人进入NJ 市,
NJ 市的交通也承受着巨大的压力。现在,NJ 市正在筹划建设一个新型的交通枢纽,从而
减轻交通的压力。
NJ 市包含n 个区,有些区之间有双向的干道存在。新型交通枢纽建设在这些干道的基
础上,将其中的部分干道改进为新型干道。改进后,干道能承受的压力可以比原来增加几十
倍。为了和谐发展,在新型的交通枢纽建成后,要求任何两个区之间都可以只通过新型干道
(直接或间接地)连接。政府已经预测出每条干道改进为新型干道的费用。政府希望建设新
型交通枢纽的总费用最小,并以巨额奖金向市民征集方案。政府很快发现费用最小的方案不
一定唯一,所以决定将奖金平分给每一种方案的第一个设计者,即如果一个人设计的费用是
最小的而且前面没人和他设计出一模一样的方案,则他可获奖。

栋栋被奖金深深的吸引,准备设计一种方案。可是,他发现方案可能会很多,如果最后
获奖者太多,巨额的资金分到每个人头上的也不会太多。所以他决定先算一下可行的方案数
是多少。
输入
输入的第一行包含两个数n (1 ≤ n ≤ 100),m (1 ≤ m ≤ 1,000),分别表示该市有
多少个区和有多少条干道。接下来m 行,每行三个数ai、bi、ci (1 ≤ ai, bi ≤ n, 1 ≤ ci ≤
1,000,000,000),表示ai 区和bi 区之间有一条干道,如果改进需要ci 的费用。
输入保证任何两个区之间至多有一条干道。对于任何一个费用c,不会有超过10 条干
道的费用都是c。
输出
输出费用最小的方案有多少种。由于答案可能很大,你只要输出方案数除以31011 的
模即可。


具体来说,就是求图的最小生成树个数

做法是先生成一遍最小生成树,记录树中各种权值的边有多少个

然后得出考虑这些边的生成树个数

某论文上有讲基尔霍夫矩阵求生成树个数的方法,十分高端

对于这道题,同一费用边不超过10个

则所以重新做一遍prim,

对于每种权值不同的边进行一遍搜索看有多少种可行解

乘起来以后随意找一种方案合并,继续寻找下一种权值不同的边

证明虽觉屌,但不明

证明:

我们用反证法来证明:假如对于图G的某一个最小生成树,其子图Gi不是一棵树,而是若干个连通块,那么由于图G是连通的,所以我们可以确定Gi中的连通块必然通过若干条其他边连起来。那么此时我们将子图中某条可以将两个连通块连接起来的边加入图中(这条边必定可以找到,因为图G’中,Gi为连通分量),这样图G的最小生成树就会形成一个环,并且这个环上必定有权值比c大的边(因为必定有边将Gi与其他子图连接起来),这时我们去掉权值比c大的边,可以得到一颗新的生成树,而且这颗生成树比最小生成树还要小,这样就产生了矛盾。



program award;
typelin=recordu,v,c:longint;end;
constmaxn=31011;
varcan:boolean;now,ans,count,s,tot,n,m,i,j,k,x,y:longint;line:array [0..1001] of lin;cop,father,dl:array [0..101] of longint;procedure swap (var a,b:lin);
vari:lin;
begini:=a;a:=b;b:=i;
end;procedure qsort (s,e:longint);
vari,j,k:longint;
beginif s>=e then exit;i:=s;j:=e;k:=line[(s+e) div 2].c;while i<=j dobeginwhile line[i].c<k do inc(i);while line[j].c>k do dec(j);if i>j then break;swap(line[i],line[j]);inc(i);dec(j);end;qsort(s,j);qsort(i,e);
end;function root (now:longint):longint;
beginif father[now]=0 then exit(now);father[now]:=root(father[now]);exit(father[now]);
end;function mother (now:longint):longint;
beginif father[now]=0 then exit(now);exit(mother(father[now]));
end;procedure search (k,s,e,left:longint);
vari,x,y:longint;
beginif k>e thenbeginif not can thenbegincop:=father;can:=true;end;inc(now);exit;end;if e-k+1>left then search(k+1,s,e,left);if left>0 thenbeginx:=mother(line[k].u);y:=mother(line[k].v);if x=y then exit;father[y]:=x;search(k+1,s,e,left-1);father[y]:=0;end;
end;beginassign(input,'award.in');reset(input);assign(output,'award.out');rewrite(output);read(n,m);if m<n-1 thenbeginwriteln(0);close(input);close(output);halt;end;if m=n-1 thenbeginwriteln(1);close(input);close(output);halt;end;for i:=1 to m doread(line[i].u,line[i].v,line[i].c);qsort(1,m);tot:=0;for i:=1 to m dobeginx:=root(line[i].u);y:=root(line[i].v);if x<>y thenbegininc(tot);dl[tot]:=line[i].c;father[x]:=y;end;if tot=n-1 then break;end;if tot<n-1 thenbeginwriteln(0);close(input);close(output);halt;end;fillchar(father,sizeof(father),0);ans:=1;i:=1;k:=1;while i<=m dobeginwhile line[i].c<>dl[k] do inc(i);s:=i;while (line[i].c=dl[k]) do inc(i);count:=1;while (k<tot)and(dl[k+1]=dl[k]) dobegininc(count);inc(k);end;inc(k);now:=0;can:=false;search(s,s,i-1,count);father:=cop;ans:=(ans*now) mod maxn;if k>tot then break;end;writeln(ans);close(input);close(output);
end.


本文发布于:2024-02-04 19:07:15,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170714376258638.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:巨额   奖金   Award
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23