首先,题目可能有多组测试数据,每个测试数据的第一行为经纪人数量N(当N=0时,输入数据结束), 然后接下来N行描述第i(1<=i<=N)个经纪人与其他经纪人的关系(教你如何画图)。每行开头数字M为 该行对应的经纪人有多少个经纪人朋友(该节点的出度,可以为0),然后紧接着M对整数,每对整数表 示成a,b,则表明该经纪人向第a个经纪人传递信息需要b单位时间(即第i号结点到第a号结点的孤长为b) ,整张图为有向图,即弧Vij 可能不等于弧Vji(数据很明显,这里是废话)。当构图完毕后,求当从该 图中某点出发,将“消息”传播到整个经纪人网络的最小时间,输出这个经纪人号和最小时间。最小时 间的判定方式为——从这个经纪人(结点)出发,整个经纪人网络中最后一个人接到消息的时。如果有 一个或一个以上经纪人无论如何无法收到消息,输出“disjoint”(有关图的连通性,你们懂得,但 据其他同学说,POJ测试数据中不会有,就是说,你不判定,一样能过,题目数据够水的)。 poj 上的测试数据 Floyd都能过//NYOJ 426 #include <stdio.h> #include <string.h> #define N 1002 #define M 100000 #define MAXTIME 100000 #define MOVE(x) (x=(x+1)%N) int nodev[N],n; int nodeu[M],data[M],next[M]; bool Build_Graph() { int i,v,u,value,m,ind; scanf("%d",&n); if(n==0) return false; memset(nodev,-1,sizeof(nodev)); ind=0; for(v=1;v<=n;v++) { scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d %d",&u,&value); ind++; next[ind]=nodev[v]; nodeu[ind]=u; data[ind]=value; nodev[v]=ind; } } return true; } bool visited[N]; bool possible[N]; int stack[N],top; void DFS(int v) { int i,u; visited[v]=true; for(i=nodev[v];i!=-1;i=next[i]) { u=nodeu[i]; if(!visited[u]) DFS(u); } } bool decision(int v) { int i; bool flag=true; for(i=1;i<=n;i++) { if(!visited[i]) { flag=false; break; } } if(!flag) { for(i=1;i<=n;i++) { if(visited[i]) possible[i]=false; } } else stack[++top]=v; return flag; } bool is_Connection() { int i,v; for(i=1;i<=n;i++) { visited[i]=false; possible[i]=true; } top=0; for(v=1;v<=n;v++) { if(possible[v]) { DFS(v); decision(v); memset(visited,false,sizeof(visited)); } } return bool(top); } int queue[N]; bool flag[N]; int time[N]; int start,mintime; void SPFA(int s) { int i,v,u,value,front,rear; for(i=1;i<=n;i++) time[i]=MAXTIME; front=-1; rear=-1; time[s]=0; memset(flag,false,sizeof(flag)); for(i=nodev[s];i!=-1;i=next[i]) { u=nodeu[i]; value=data[i]; time[u]=value; queue[MOVE(rear)]=u; flag[u]=true; } //while(front<rear)//这里!!!!!!!!! while(front!=rear) { v=queue[MOVE(front)]; flag[v]=false; for(i=nodev[v];i!=-1;i=next[i]) { u=nodeu[i]; value=data[i]; if(time[v]+value<time[u]) { time[u]=time[v]+value; if(!flag[u]) { queue[MOVE(rear)]=u; flag[u]=true; } } } } } void solve() { int s,i,v,temp; mintime=MAXTIME; for(v=1;v<=top;v++) { s=stack[v]; SPFA(s); temp=0; for(i=1;i<=n;i++) { if(time[i]>temp) temp=time[i]; } if(temp<mintime) { mintime=temp; start=s; } } } int main() { while(1) { if(!Build_Graph()) break; if(is_Connection()) { solve(); printf("%d %d\n",start,mintime); } else printf("disjoint\n"); } return 0; }
poj 1125 有点水
Floyd
/*
经典水题floyd这道题重点在于找到从某一个源点出发的最短路
怎么找?可以找到从一个源点出发最长的时间,即是传递结束,
然后找最长的最短。当然会出现有些人没有传递到,但是这道
题的bug在于此,不会出现disjoint的情况。
*/
#include<iostream>
#include<cstring>
using namespace std;
#define inf 20
#define M 210
int dist[M][M];
int 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(i != j && dist[i][j] > dist[i][k] + dist[k][j])
dist[i][j] = dist[i][k] + dist[k][j];
int minlength = inf;
int maxlength,pos;
for(int i = 1;i <= n; i++){
maxlength = 0;
for(int j = 1;j <= n; j++)
if(i != j && maxlength < dist[i][j])
maxlength = dist[i][j];
if(minlength > maxlength){
minlength = maxlength;
pos = i;
}
}
cout<<pos<<" "<<minlength<<endl;;
}
int main()
{
while(1){
memset(dist,inf,sizeof(dist));
cin>>n;
if(!n)
break;
for(int i = 1;i <= n; i++){
int n1;
cin>>n1;
for(int j = 1;j <= n1; j++){
int p,t;
cin>>p>>t;
dist[i][p] = t;
}
}
floyd();
}
return 0;
}