您的位置:首页 > 其它

哈理工oj 1339-Touring解题报告

2012-04-11 21:10 357 查看
链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1339

这道题是用dijkstra求最短路径,然后找出三个点到一个点的最小路径总和,数据量很大,所以一般朴素的dijkstra会超时,所以采用堆优化,纠结啊,调了一天,最后才想明白怎么处理不可达的情况,这是很多网上给出的堆优化难以解决的问题,也算是学了些东西了。其实学ACM重要的就是这种耐心和灵感。

View Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define N 5005
using namespace std;
const int NoEdge=0xfffffff;
int size,n;
struct node
{
int n;
int v;
};
node heap[2*N];
int ph
;
bool used
;
vector<node> g
;
int da
,db
,dc
;
int parent(int i)
{
return i>>1;
}
int left(int i)
{
return i<<1;
}
int right(int i)
{
return (i<<1)+1;
}
void MIN_HEAPIFY(int i)//最小根堆
{
node temp;
int small=i;
if(left(i)<=size&&heap[left(i)].v<heap[i].v)
small=left(i);
if(right(i)<=size&&heap[right(i)].v<heap[small].v)
small=right(i);
if(small!=i)
{
ph[heap[small].n]=i;
ph[heap[i].n]=small;
temp=heap[i];
heap[i]=heap[small];
heap[small]=temp;
MIN_HEAPIFY(small);
}
}
node extract_min()//取根节点
{
node min=heap[1];
heap[1]=heap[size--];
ph[heap[1].n]=1;
MIN_HEAPIFY(1);
return min;
}
void decrease(int i,int k)//更新节点的权值
{
heap[i].v=k;
int j;
while(i>1&&heap[i].v<heap[parent(i)].v)
{
ph[heap[parent(i)].n]=i;
ph[heap[i].n]=parent(i);
node temp;
temp=heap[i];
heap[i]=heap[parent(i)];
heap[parent(i)]=temp;
i=parent(i);
}
}
bool empty()
{
return size==0;
}
void dijkstra(int s,int *d)
{
int i,j;
for(i=1;i<=n;i++)
{
heap[i].n=i;
heap[i].v=NoEdge;
ph[i]=i;
}
decrease(s,0);
node min;
while(!empty())
{
min=extract_min();
d[min.n]=min.v;
used[min.n]=true;//已经发现要记住
int num=g[min.n].size();
for(i=0;i<num;i++)
{
if(!used[g[min.n][i].n]&&heap[ph[g[min.n][i].n]].v>min.v+g[min.n][i].v)
{
decrease(ph[g[min.n][i].n],min.v+g[min.n][i].v);
}
}
}
}
int main()
{
int i,j;
int s,t;
int dis;
int a,b,c;
int m;
node temp;
int icase=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(used,0,sizeof(used));
for(i=1;i<=n;i++)
g[i].clear();
scanf("%d%d%d",&a,&b,&c);
size=n;
for(i=1;i<=n;i++)
{
da[i]=db[i]=dc[i]=NoEdge;
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&s,&t,&dis);
temp.n=t;
temp.v=dis;
g[s].push_back(temp);
temp.n=s;
g[t].push_back(temp);
}
printf("Scenario #%d\n",icase++);
dijkstra(a,da);
if(da[b]==NoEdge||da[c]==NoEdge)
{
printf("Can not reah!\n\n");
continue;
}
size=n;
memset(used,0,sizeof(used));
dijkstra(b,db);
size=n;
memset(used,0,sizeof(used));
dijkstra(c,dc);
int max=NoEdge;
for(i=1;i<=n;i++)
{
if(da[i]!=NoEdge&&dc[i]+da[i]+db[i]<max)//寻找最小的总权值
{
max=dc[i]+da[i]+db[i];
}
}
printf("%d\n\n",max);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: