哈理工oj 1339Touring解题报告

链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1339

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

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #define N 5005
  6 using namespace std;
  7 const int NoEdge=0xfffffff;
  8 int size,n;
  9 struct node
 10 {
 11     int n;
 12     int v;
 13 };
 14 node heap[2*N];
 15 int ph[N];
 16 bool used[N];
 17 vector<node> g[N];
 18 int da[N],db[N],dc[N];
 19 int parent(int i)
 20 {
 21     return i>>1;
 22 }
 23 int left(int i)
 24 {
 25     return i<<1;
 26 }
 27 int right(int i)
 28 {
 29     return (i<<1)+1;
 30 }
 31 void MIN_HEAPIFY(int i)//最小根堆
 32 {
 33     node temp;
 34     int small=i;
 35     if(left(i)<=size&&heap[left(i)].v<heap[i].v)
 36     small=left(i);
 37     if(right(i)<=size&&heap[right(i)].v<heap[small].v)
 38     small=right(i);
 39     if(small!=i)
 40     {
 41         ph[heap[small].n]=i;
 42         ph[heap[i].n]=small;
 43         temp=heap[i];
 44         heap[i]=heap[small];
 45         heap[small]=temp;
 46         MIN_HEAPIFY(small);
 47     }
 48 }
 49 node extract_min()//取根节点
 50 {
 51     node min=heap[1];
 52     heap[1]=heap[size--];
 53     ph[heap[1].n]=1;
 54     MIN_HEAPIFY(1);
 55     return min;
 56 }
 57 void decrease(int i,int k)//更新节点的权值
 58 {
 59     heap[i].v=k;
 60     int j;
 61     while(i>1&&heap[i].v<heap[parent(i)].v)
 62     {
 63         ph[heap[parent(i)].n]=i;
 64         ph[heap[i].n]=parent(i);
 65         node temp;
 66         temp=heap[i];
 67         heap[i]=heap[parent(i)];
 68         heap[parent(i)]=temp;
 69         i=parent(i);
 70     }
 71 }
 72 bool empty()
 73 {
 74     return size==0;
 75 }
 76 void dijkstra(int s,int *d)
 77 {
 78     int i,j;
 79     for(i=1;i<=n;i++)
 80     {
 81         heap[i].n=i;
 82         heap[i].v=NoEdge;
 83         ph[i]=i;
 84     }
 85     decrease(s,0);
 86     node min;
 87     while(!empty())
 88     {
 89         min=extract_min();
 90         d[min.n]=min.v;
 91         used[min.n]=true;//已经发现要记住
 92         int num=g[min.n].size();
 93         for(i=0;i<num;i++)
 94         {
 95             if(!used[g[min.n][i].n]&&heap[ph[g[min.n][i].n]].v>min.v+g[min.n][i].v)
 96             {
 97                 decrease(ph[g[min.n][i].n],min.v+g[min.n][i].v);
 98             }
 99         }
100     }
101 }
102 int main()
103 {
104     int i,j;
105     int s,t;
106     int dis;
107     int a,b,c;
108     int m;
109     node temp;
110     int icase=1;
111     while(scanf("%d%d",&n,&m)!=EOF)
112     {
113         memset(used,0,sizeof(used));
114         for(i=1;i<=n;i++)
115         g[i].clear();
116         scanf("%d%d%d",&a,&b,&c);
117         size=n;
118         for(i=1;i<=n;i++)
119         {
120             da[i]=db[i]=dc[i]=NoEdge;
121         }
122         for(i=0;i<m;i++)
123         {
124             scanf("%d%d%d",&s,&t,&dis);
125             temp.n=t;
126             temp.v=dis;
127             g[s].push_back(temp);
128             temp.n=s;
129             g[t].push_back(temp);
130         }
131         printf("Scenario #%d\n",icase++);
132         dijkstra(a,da);
133         if(da[b]==NoEdge||da[c]==NoEdge)
134         {
135             printf("Can not reah!\n\n");
136             continue;
137         }
138         size=n;
139         memset(used,0,sizeof(used));
140         dijkstra(b,db);
141         size=n;
142         memset(used,0,sizeof(used));
143         dijkstra(c,dc);
144         int max=NoEdge;
145         for(i=1;i<=n;i++)
146         {
147             if(da[i]!=NoEdge&&dc[i]+da[i]+db[i]<max)//寻找最小的总权值
148             {
149                 max=dc[i]+da[i]+db[i];
150             }
151         }
152         printf("%d\n\n",max);
153     }
154     return 0;
155 }
原文地址:https://www.cnblogs.com/caozhenhai/p/2442972.html