Stockbroker Grapevine
Floyd&Dijkstra
描述
众所周知,股票经纪人对谣言反应过度。您已签约开发一种在股票经纪人之间传播虚假信息的方法,以使您的雇主在股票市场上具有战术上的优势。为了获得最大效果,您必须以最快的方式传播谣言。
对于您来说不幸的是,股票经纪人仅信任来自其“受信任来源”的信息。这意味着在开始谣言时,您必须考虑其联系方式。一个特定的股票经纪人将谣言传给他的每个同事都需要花费一定的时间。
您的任务是编写一个程序,该程序告诉您选择哪个股票经纪人作为谣言的起点,以及该谣言传播到整个股票经纪人社区所需的时间。该持续时间以最后一个人接收信息所需的时间来衡量。
.
输入项
您的程序将输入不同组股票经纪人的数据。每组第一行是股票经纪人的数量。接下来每行是每个股票经纪人,其中包含与他们联系的人数,这些人的身份以及他们将消息传递给每个人所花费的时间。每个股票经纪人的格式如下:该行以联系人数量(n)开头,后跟n对整数,每个联系人一对。每对首先列出一个引用联系人的编号 (例如,“ 1”表示联系人中的第一个人),然后是将消息传递给该个人所花费的时间(以分钟为单位)。没有特殊的标点符号或间距规则。
每个人的编号从1到股票经纪人的数量。传递消息所花费的时间将在1到10分钟(含)之间,并且联系人的数量将在0到股票经纪人的数量少1之间。股票经纪人的数量范围为1到100。输入由一组包含0(零)人的股票经纪人终止。
.
输出量
对于每组数据,您的程序必须输出一行,其中包含使消息发送最快的起始人员,以及在您将该消息发送给此人之后,最后一个人将收到给定消息的时间(以整数分钟为单位)。
您的程序可能会收到一个连接网络,该连接网络将某些人排除在外,即某些人可能无法访问。如果您的程序检测到这种断开的网络,只需输出消息“ disjoint”。注意,将消息从A传递到B所花费的时间不一定与将消息从B传递给A所花费的时间相同。
.
Sample Input
3
2 2 4 3 5
2 1 2 3 6
2 1 2 2 2
.
5
3 4 4 2 8 5 3
1 5 8
4 1 6 4 10 2 7 5 2
0
2 2 5 1 5
0
.
Sample Output
3 2
3 10
先上漂亮一点的Floyd
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 105;
const int oo = 0x3fffff;
int n,g[N][N];
void floyd(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
}
int main(){
while(~(scanf("%d",&n))){
if(n==0) break;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j) g[i][j] = oo;//
for(int i=1,m;i<=n;i++){
scanf("%d",&m);
for(int j=1,y,t;j<=m;j++){
scanf("%d%d",&y,&t);
g[i][y]=t;
}
}
floyd();
int minn=oo,f;
for(int i=1;i<=n;i++){
int maxn=0;
for(int j=1;j<=n;j++)
maxn = max(g[i][j],maxn);
if(minn>maxn) {
minn=maxn;
f=i;
}
}
if(minn==oo) printf("disjoint\n");
else printf("%d %d\n",f,minn);
}
return 0;
}
下面是麻烦一点但也能过的Dijkstra
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int oo = 0x3fffff;
const int N = 105;
int n,en,maxx,head[N],dis[N];
bool visited[N];
struct Edge{
int to,next,w;
}edge[N*N];
void add(int x,int y,int t){
edge[++en].to = y;
edge[en].w = t;
edge[en].next = head[x];
head[x] = en;
}
void dijk(){
for(int i=1;i<n;i++){
int minn=oo+1,p=-1;
for(int j=1;j<=n;j++)
if(!visited[j] && minn>dis[j]){
minn=dis[j];
p=j;
}
if(p==-1) break;
visited[p]=true;
for(int k=head[p];k;k=edge[k].next ){
int v=edge[k].to ;
if(dis[v]>edge[k].w+dis[p]&&!visited[v])
dis[v]=edge[k].w+dis[p];
}
}
}
int main(){
while(~scanf("%d",&n)){
if(n==0) break;
int minx=oo,f;
en=0;
memset(head,0,sizeof(head));
for(int i=1,m;i<=n;i++){
scanf("%d",&m);
for(int j=1,y,t;j<=m;j++){
scanf("%d%d",&y,&t);
add(i,y,t);
}
}
for(int i=1;i<=n;i++){//i为起始点
for(int j=1;j<=n;j++)
if(j==i) dis[j]=0;
else dis[j]=oo;
memset(visited,0,sizeof(visited)); //memset(a,0,sizeof(a)) 最后一个是长度aaaaaaa
dijk();
// for(int j=1;j<=n;j++)printf("%d ",dis[j]);
// printf("\n\n"); 不用管这个输出调试
int maxx=0;
for(int j=1;j<=n;j++)
if(maxx<dis[j]) maxx=dis[j];
if(minx>maxx) {
minx=maxx;
f=i;
}
}
if(minx==oo) printf("disjoint\n");
else printf("%d %d\n",f,minx);
}
return 0;
}
解题思路hin简单:
对每个测试点:以每个点为出发点进行最短路,得到消息传到每个点的最短时间,这些最短时间中求一个最大的为整体需要的时间;在不同出发点的情况中取整体需要时间最少的一个作为最终答案。
Dijkstra——以每个点为出发点进行一遍dijk,然后取最大dist中的最小值;
Floyd——直接把到达任意两个点的最短路径求出来,然后以不同点为出发点时再搜出一个最大距离,整体再求最小值。
坎坷的coding历程:
1.不会memset哈哈哈哈哈哈哈哈哈哈哈哈哈
memset | fill | |
---|---|---|
头文件 | cstring | algorithm |
语句写法(举例) | memset(a,0,sizeof(a)); | fill(a,a+N,0); |
可填充数字 | 只有0或-1 | 所有数字都可以 |
可填充数组类型 | n维都可以 | n维都可以,只是有特殊格式 |
说明:
memset是按字节填充,所以是cstring而且只能填0和-1。 0是000…0,-1是111…1(-1原码1000…1,补码111…1)别的一填就乱了
如果有二维数组b[N][M],则填充时fill(b[0],b[0]+M*N,x); 二维数组的地址是b[0],注意没有“b[1]表示地址”这种东西,只有多维数组少一个维度来表示地址的
- 多个测试点初始化做到位…每次都只能后面调试的时候救火一样加语句
真是没得法
2019.10.24.(嗯今天程序员日???)