#10064. 「一本通 3.1 例 1」黑暗城堡
题目描述
你知道黑暗城堡有 NNN 个房间,MMM 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设 DiD_iDi? 为如果所有的通道都被修建,第 iii 号房间与第 111 号房间的最短路径长度;
而 SiS_iSi? 为实际修建的树形城堡中第 iii 号房间与第 111 号房间的路径长度;
要求对于所有整数 iii (1≤i≤N1\le i\le N1≤i≤N),有 Si=DiS_i= D_iSi?=Di? 成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 231−12^{31} -1231−1 取模之后的结果就行了。
输入格式
第一行为两个由空格隔开的整数 N,MN, MN,M;
第二行到第 M+1M+1M+1 行为 333 个由空格隔开的整数 x,y,lx, y, lx,y,l:表示 xxx 号房间与 yyy 号房间之间的通道长度为 lll。
输出格式
一个整数:不同的城堡修建方案数对 231−12^{31} -1231−1 取模之后的结果。
样例
样例输入
4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1
样例输出
6
样例说明
一共有 444 个房间,666 条道路,其中 111 号和 222 号,111 号和 333 号,111 号和 444 号,222 号和 333 号,222 号和 444 号,333 号和 444 号房间之间的通道长度分别为 111,222,333,111,222,111。
而不同的城堡修建方案数对 231−12^{31} -1231−1 取模之后的结果为 666。
先跑一次最短路,再将每一个点的方案数算出来,根据乘法远离相乘
1 #include <bits/stdc++.h> 2 using namespace std; 3 const long long mod = (1 << 31) - 1; 4 const int maxn = 1010; 5 const int maxm = 1e6; 6 int n, m, head[maxn], size, mp[maxn][maxn], dis[maxn]; 7 bool bj[maxn]; 8 long long ans = 1; 9 struct edge { 10 int v, nex, w; 11 } e[maxm << 1]; 12 13 struct node { 14 int pos, cost; 15 node(int pos = 0, int cost = 0) : pos(pos), cost(cost) {} 16 friend bool operator<(node a, node b) { return a.cost > b.cost; } 17 }; 18 19 void adde(int u, int v, int w) { 20 e[size].v = v; 21 e[size].w = w; 22 e[size].nex = head[u]; 23 head[u] = size++; 24 } 25 26 void spfa() { 27 dis[1] = 0, bj[1] = 0; 28 priority_queue<node> q; 29 q.push(node(1, 0)); 30 while (!q.empty()) { 31 node a = q.top(); 32 q.pop(); 33 bj[a.pos] = 0; 34 int u = a.pos; 35 for (int i = head[u]; ~i; i = e[i].nex) { 36 int v = e[i].v, w = e[i].w; 37 if (dis[v] > dis[u] + w) { 38 dis[v] = dis[u] + w; 39 if (!bj[v]) { 40 bj[v] = 1; 41 q.push(node(v, dis[v])); 42 } 43 } 44 } 45 } 46 } 47 48 int main() { 49 // freopen("in.txt","r",stdin); 50 memset(head, -1, sizeof(head)); 51 memset(mp, 0x3f, sizeof(mp)); 52 memset(dis, 0x3f, sizeof(dis)); 53 scanf("%d%d", &n, &m); 54 for (int i = 1; i <= m; i++) { 55 int u, v, w; 56 scanf("%d%d%d", &u, &v, &w); 57 mp[u][v] = mp[v][u] = min(mp[u][v], w); 58 adde(u, v, w); 59 adde(v, u, w); 60 } 61 spfa(); 62 for (int i = 2; i <= n; i++) { 63 long long cnt = 0; 64 for (int j = 1; j <= n; j++) { 65 if (mp[j][i] < 300 && dis[j] + mp[j][i] == dis[i]) 66 cnt++; 67 } 68 ans = (ans * cnt) % mod; 69 // printf("%d\n",ans); 70 } 71 printf("%lld", ans); 72 return 0; 73 }
「一本通 3.1 例 2」北极通讯网络
题目描述
原题来自:Waterloo University 2002
北极的某区域共有 nnn 座村庄,每座村庄的坐标用一对整数 (x,yx, yx,y) 表示。为了加强联系,决定在村庄之间建立通讯网络。通讯工具可以是无线电收发机,也可以是卫星设备。所有的村庄都可以拥有一部无线电收发机, 且所有的无线电收发机型号相同。但卫星设备数量有限,只能给一部分村庄配备卫星设备。
不同型号的无线电收发机有一个不同的参数 ddd,两座村庄之间的距离如果不超过 ddd 就可以用该型号的无线电收发机直接通讯,ddd 值越大的型号价格越贵。拥有卫星设备的两座村庄无论相距多远都可以直接通讯。
现在有 kkk 台卫星设备,请你编一个程序,计算出应该如何分配这 kkk 台卫星设备,才能使所拥有的无线电收发机的 ddd 值最小,并保证每两座村庄之间都可以直接或间接地通讯。
例如,对于下面三座村庄:
其中 ∣AB∣=10,∣BC∣=20,∣AC∣=105≈22.36|AB|= 10, |BC|= 20, |AC|= 10\sqrt{5}≈22.36∣AB∣=10,∣BC∣=20,∣AC∣=105
?≈22.36
如果没有任何卫星设备或只有 111 台卫星设备 (k=0k=0k=0 或 k=1k=1k=1),则满足条件的最小的 d=20d = 20d=20,因为 AAA 和 BBB,BBB 和 CCC 可以用无线电直接通讯;而 AAA 和 CCC 可以用 BBB 中转实现间接通讯 (即消息从 AAA 传到 BBB,再从 BBB 传到 CCC);
如果有 222 台卫星设备 (k=2k=2k=2),则可以把这两台设备分别分配给 BBB 和 CCC ,这样最小的 ddd 可取 101010,因为 AAA 和 BBB 之间可以用无线电直接通讯;BBB 和 CCC 之间可以用卫星直接通讯;AAA 和 CCC 可以用 BBB 中转实现间接通讯。
如果有 333 台卫星设备,则 A,B,CA,B,CA,B,C 两两之间都可以直接用卫星通讯,最小的 ddd 可取 000。
输入格式
第一行为由空格隔开的两个整数 n,kn,kn,k;
第 2∼n+12\sim n+12∼n+1 行,每行两个整数,第 iii 行的 xi,yix_i,y_ixi?,yi? 表示第 iii 座村庄的坐标 (xi,yix_i, y_ixi?,yi?)。
输出格式
一个实数,表示最小的 ddd 值,结果保留 222 位小数。
样例
样例输入
3 2
10 10
10 0
30 0
样例输出
10.00
数据范围与提示
即求最小生成树第k长的边
证明过程可参考 https://www.cnblogs.com/mxrmxr/p/9846958.html
先将dis数组的值初始化成与第一个借点的距离,即默认第一个点已在生成树上,在进行加边操作
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=505; 4 int dis[maxn],n,k,x[maxn],y[maxn]; 5 bool vis[maxn]; 6 int cc(int a,int b){ 7 return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]); 8 } 9 bool cmp(int a,int b){ 10 return a>b; 11 } 12 int main(){ 13 scanf("%d%d",&n,&k); 14 for(int i=1;i<=n;i++){ 15 scanf("%d%d",x+i,y+i); 16 dis[i]=cc(1,i); 17 } 18 for(int i=1;i<n;i++){ 19 int minn=1e9,pos; 20 for(int j=2;j<=n;j++) if(!vis[j]&&dis[j]<minn) minn=dis[pos=j]; 21 vis[pos]=1; 22 for(int j=2;j<=n;j++) if(!vis[j]) dis[j]=min(dis[j],cc(j,pos)); 23 } 24 sort(dis+1,dis+1+n,cmp); 25 printf("%.2f",sqrt(dis[k])); 26 return 0; 27 }
原文地址:https://www.cnblogs.com/plysc/p/10408311.html