您的位置:首页 > 其它

Hdu 2145 zz's Mysterious Present 解题分析

2008-05-01 10:40 375 查看
题意:输入城市数n, 朋友数m,道路数k,再输入k条路,zz所在城市编号,m个朋友的城市编号,m个朋友的速度。最快到达zz所在城市的朋友得到礼物,若同时到时距离远的朋友得到礼物,若同时到距离也相同时编号大的朋友得到礼物。本题主要解题思路是求最短路径,然后找最小值。注意是有向图。
本题2个可能的Bug,(1)可能m>n;(2)第一个朋友可能肯定可以到达zz所在城市。
本题用m次Dijkstra要超时,怎么办?处理技巧:把终点做起点,所有边反方向处理。
#include<iostream>
#include<vector>
using namespace std;

const int MAX=30001; //根据题目算出

vector <vector <int> > mat;
vector <bool> visited;
vector <int> dist;
int n;

int minVertex()
{
int next=-1;
for (int i=0;i<n;i++)
if (!visited[i] && (next==-1 || dist[i]<dist[next]))
next=i;
return next;
}

struct Who
{
double t;//为便于写比较函数
int p;
int id;
};

bool cmp(Who a,Who b)
{
if (a.t==b.t)
{
if (dist[a.p]==dist[b.p])//注意是距离的比较
return a.id>b.id;
else
return dist[a.p]>dist[b.p];
}
else
return a.t<b.t;
}

void Dijkstra(int source)
{
dist=mat[source];
fill(visited.begin(),visited.end(),false);
visited[source]=true;
while(true)
{
int next=minVertex();
if (next==-1) break;
visited[next]=true;

for (int i=0; i<n; i++)
if (!visited[i] && dist[i]>mat[next][i]+dist[next])
dist[i]=mat[next][i]+dist[next];
}
}

bool run()
{
int m,k,i;
if(scanf("%d%d%d",&n,&m,&k)==EOF) return false;

mat.resize(n);
for(i=0;i<n;i++)
{
mat[i].resize(n);
fill(mat[i].begin(),mat[i].end(),MAX);
mat[i][i]=0;
}

for( i=0;i<k;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
a--;
b--;
mat[b][a]=c;//反方向处理
}

int start;
scanf("%d",&start);
start--;
visited.resize(n);
Dijkstra(start);

vector <int> p(m);
vector <int> speed(m);

for(i=0;i<m;i++)
{
scanf("%d",&p[i]);
p[i]--;
}

for(i=0;i<m;i++)
{
scanf("%d",&speed[i]);
}

Who r={INT_MAX,0,0}; //假设时间不超过INT_MAX
int cnt=0; //其实这个变量可以不要的
for(i=0;i<m;i++)
{
if (dist[p[i]]!=MAX)
{
Who w;
w.t=dist[p[i]]*1.0/speed[i];
w.id=i+1;
w.p=p[i];
if(cmp(w,r)==true) r=w;
}
else
{
cnt++;
}
}

if (cnt==m)
printf("No one/n");
else
printf("%d/n",r.id);

return true;
}

int main()
{
while(run());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: