题意:选定一个经纪人散步传闻,计算所有经纪人都收到这个过程的最少时间。
思路:求解n次单源最短路径,取单源最短路径中的最大值,使最大值最小。
poj上的数据很水,南阳oj的数据有所加强 http://acm.nyist.net/JudgeOnline/problem.php?pid=426
求单源最短路径之前,先判连通,若从一点无法走到其他所有点,则没必要从这个点出发,可以直接考虑其他点。
spfa代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int inf = 100000;
const int maxn = 1005;
struct node{
int v;
int w;
node(int _v, int _w){
v = _v; w = _w;
}
};
int n;
vector<node> list[maxn];
int dist[maxn];
bool inq[maxn];
bool vis[maxn];
bool input(){
scanf("%d",&n);
if(n == 0) return false;
//clear
for(int i = 1 ; i <= n; i++) list[i].clear();
int m;
int v,w;
for(int i = 1; i <= n; i++){
scanf("%d",&m);
for(int j = 0; j < m; j++){
scanf("%d%d",&v,&w);
list[i].push_back(node(v,w));
}
}
return true;
}
void spfa(int s){
queue<int> q;
for(int i = 1; i <= n; i++){
dist[i] = inf;
inq[i] = false;
}
dist[s] = 0;
q.push(s);
while(!q.empty()){
int u = q.front(); q.pop(); inq[u] = false;
for(int i = 0; i < list[u].size(); i++){
int v = list[u][i].v;
int edge = list[u][i].w;
if(dist[u] + edge < dist[v]){
dist[v] = dist[u] + edge;
if(!inq[v]){
q.push(v); inq[v] = true;
}
}
}
}//end of while
}
void dfs(int s){
vis[s] = true;
for(int i = 0; i < list[s].size(); i++){
int v = list[s][i].v;
if(!vis[v]){
dfs(v);
}
}
}
void solve(){
int minimum = inf;
int pos;
for(int i = 1; i <= n; i++){
//dfs判连通
for(int j = 1; j <= n; j++) vis[j] = false;
dfs(i);
bool fg = false;
for(int j = 1; j <= n; j++)
if(!vis[j]){
fg = true;
break;
}
if(fg) continue;
spfa(i);
int maximum = -inf;
for(int j = 1; j <= n; j++){
if(dist[j] > maximum)
maximum = dist[j];
if(maximum == inf) break;//不能全部收到传闻
}
if(maximum != inf && maximum < minimum){
minimum = maximum;
pos = i;
}
}//end of for
if(minimum == inf) puts("disjoint\n");
else printf("%d %d\n",pos,minimum);
}
int main(){
while(input()){
solve();
}
return 0;
}
优先队列+dijkstra:
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int inf = 100000;
const int maxn = 1005;
struct node{
int v;
int w;
node *next;
node(){
v = 0; w = 0; next = NULL;
}
};
struct qnode{//为优先队列使用
int w;
int index;
qnode(int _w, int _index){
w = _w; index = _index;
}
bool operator < (const qnode &b) const{
return w > b.w;
}
};
int n;
node* list[maxn];
int dist[maxn];
bool vis[maxn]; //dijkstra算法是否访问过
bool vis2[maxn]; //dfs
void list_init(){//对每个链建立一个哨兵
for(int i = 0; i < maxn; i++)
list[i] = new node;
}
void list_clear(){
for(int i = 0; i <= n; i++){
node *p = list[i];
while(p->next){
node *t = p->next;
p->next = t->next;
delete t;
}
}
}
bool input(){
scanf("%d",&n);
if(n == 0) return false;
//clear
list_clear();
int m;
int v,w;
for(int i = 1; i <= n; i++){
scanf("%d",&m);
node *p = list[i];//哨兵
for(int j = 0; j < m; j++){
node *t = new node;
scanf("%d%d",&t->v,&t->w);
//头插
t->next = p->next;
p->next =t;
}
}
return true;
}
void dijkstra(int s){
priority_queue<qnode> q;
for(int i = 1; i <= n; i++){
dist[i] = inf; vis[i] = false;
}
dist[s] = 0;
q.push(qnode(0,s));
while(!q.empty()){
int u = q.top().index; q.pop();
if(vis[u]) continue;
vis[u] = true;
node *p = list[u]->next;
while(p){
int v = p->v;
int edge = p->w;
if(!vis[v] && dist[u] + edge < dist[v]){
dist[v] = dist[u] + edge;
q.push(qnode(dist[v],v));
}
p = p->next;
}
}//end of while
}
void dfs(int s){
vis2[s] = true;
node *p = list[s]->next;
while(p){
int v = p->v;
if(!vis2[v]){
dfs(v);
}
p = p->next;
}
}
void solve(){
int minimum = inf;
int pos;
for(int i = 1; i <= n; i++){
//dfs判断能否走通
for(int j = 1; j <= n; j++) vis2[j] = false;
dfs(i);
bool fg = false;
for(int j = 1; j <= n; j++) {
if(vis2[j] == false) {
fg = true; break;
}
}
if(fg) continue;
dijkstra(i);
int maximum = -inf;
for(int j = 1; j <= n; j++){
if(dist[j] > maximum)
maximum = dist[j];
if(maximum == inf) break;//不能全部收到传闻
}
if(maximum != inf && maximum < minimum){
minimum = maximum;
pos = i;
}
}//end of for
if(minimum == inf) puts("disjoint\n");
else printf("%d %d\n",pos,minimum);
}
int main(){
list_init();
while(input()){
solve();
}
return 0;
}