您的位置:首页 > 其它

hdu1598 find the most comfortable road (枚举+并查集)

2012-02-13 21:17 567 查看
中文题,题意就不说了

不过想不到并查集这样用

对于题目中的路,按速度进行排序,这样,如果从第 i 条路到第 j 条路之间的所有路能够让 i 和 j 连通,那么,这就存在一条路,且这条路的舒适度就是 两者的差值。 这样,只要枚举从每一条路开始,向前找到可以使得 起点和终点连通的路的舒适度,就可以找到答案了

View Code

#include"iostream"
#include"queue"
#include"algorithm"
#define MAXN 205
#define MAXM 2005
#define inf 0x3f3f3f3f
using namespace std;
struct ee
{
int u,v,c;
}edge[MAXM];
struct edges
{
int u,c,next;
}e[MAXM];
int N,M,idx;
int p[MAXN],dist[MAXN];
bool used[MAXN];
queue<int>q;
bool cmp(ee a,ee b)
{
return a.c<b.c;
}
void init()
{
idx=0;
memset(p,0xff,sizeof(p));
}
void addedge(int u,int v,int c)
{
e[idx].u=v;
e[idx].c=c;
e[idx].next=p[u];
p[u]=idx++;
}
void spfa(int s)
{
int t,u,w;
while(!q.empty())q.pop();
memset(used,false,sizeof(used));
for(int i=0;i<N;i++)
dist[i]=inf;
dist[s]=0;
q.push(s);
while(!q.empty())
{
t=q.front();
q.pop();
used[t]=false;
for(int i=p[t];i!=-1;i=e[i].next)
{
u=e[i].u;
w=e[i].c;
if(dist[t]+w<dist[u])
{
dist[u]=dist[t]+w;
if(!used[u])
{
used[u]=true;
q.push(u);
}
}
}
}
}
int main(){
int a,b,K,l,h,ll,hh,mid,low;
while(scanf("%d%d",&N,&M)==2)
{
for(int i=0;i<M;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);
edge[i].u--;
edge[i].v--;
}
sort(edge,edge+M,cmp);
hh=edge[M-1].c-edge[0].c;
ll=inf;
for(int i=1;i<M;i++)
{
if(edge[i].c-edge[i-1].c<ll)
ll=edge[i].c-edge[i-1].c;
}
scanf("%d",&K);
bool flag=false;
int res=-1;
while(K--)
{
scanf("%d%d",&a,&b);
a--;b--;
l=ll,h=hh;
res=-1;
while(l<=h)//二分逼近满足条件的最小差值
{
flag=false;
mid=(l+h)>>1;
for(int i=0;i<M;i++)
{
low=edge[i].c;
init();
for(int j=i;j<M;j++)//选出所有满足当前差值的边
{
if(edge[j].c>low+mid)
break;
addedge(edge[j].u,edge[j].v,1);
addedge(edge[j].v,edge[j].u,1);
}
spfa(a);
if(dist[b]!=inf)//判断是否可达
{
flag=true;
break;
}
}
if(flag)
{
res=mid;
h=mid-1;
}
else l=mid+1;
}
printf("%d\n",res);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: