1.上午四个小时
完成了两个题目。
建立双向图需要注意,添加边的时候第一次是一个方向(a,b,c),第二次是相反的方向(b,a,c),边的起点和终点要交换。一开始就卡在这里。
P1629 邮递员送信
P1629 邮递员送信 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路
邮递员每次只能送一个包裹,所以需要多次返回邮局,因此要建立双向的图,然后就利用迪杰斯特拉算法的标准版就可以了。
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=100001;
const int zz=0x7fffffff;
const int M=500001;
int n,m,s=1,cnt=0,e,f,g,h;
int head[N],dist[N];
bool vis[N];
long long sum;
struct edge
{
int to;
int weight;
int next;
} edge[M];
struct node
{
int idex;
int way;
bool operator<(const node &x) const
{
return x.way<way;
}
};
void addedge(int a,int b,int v)
{
cnt++;
edge[cnt].to=b;
edge[cnt].weight=v;
edge[cnt].next=head[a];
head[a]=cnt;
}
void dij(int s)
{
for(int i=1; i<=2*n; i++)
{
vis[i]=false;
dist[i]=zz;
}
dist[s]=0;
priority_queue<node> q;
q.push({s,0});
while(q.size())
{
int bb=q.top().idex;
q.pop();
if(vis[bb])
continue;
vis[bb]=true;
for(int i=head[bb]; i; i=edge[i].next)
{
if(!vis[edge[i].to]&&dist[edge[i].to]>dist[bb]+edge[i].weight)
{
dist[edge[i].to]=dist[bb]+edge[i].weight;
q.push({edge[i].to,dist[edge[i].to]});
}
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d %d %d",&f,&g,&h);
addedge(f,g,h);
addedge(g+n,f+n,h);
}
dij(1);
for(int i=2; i<=n; i++)
sum+=dist[i];
dij(1+n);
for(int i=2+n; i<=2*n; i++)
sum+=dist[i];
printf("%lld",sum);
return 0;
}
P1339 [USACO09OCT]Heat Wave G
P1339 [USACO09OCT]Heat Wave G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路
首先建立无向图,然后套用迪杰斯特拉算法的弱化版,但要注意有点不同就是这题多了终点,还有是双向的。
代码实现
#include<bits/stdc++.h>
using namespace std;
int head[10001];
int n,m,s,t,o,p,q,cnt;
bool vis[10001];
long long dist[10001];
struct Edge
{
int to;
int weight;
int next;
}edge[500001];
void addedge(int a,int b,int v)
{
cnt++;
edge[cnt].to=b;
edge[cnt].weight=v;
edge[cnt].next=head[a];
head[a]=cnt;
}
void dij()
{
for(int i=1;i<=n;i++)
{
dist[i]=2147483647;
vis[i]=false;
}
dist[s]=0;
int idex=s;
while(!vis[idex])
{
vis[idex]=true;
for(int i=head[idex];i!=0;i=edge[i].next)
{
if(!vis[edge[i].to]&&dist[edge[i].to]>dist[idex]+edge[i].weight)
{
dist[edge[i].to]=dist[idex]+edge[i].weight;
}
}
int Min=2147483647;
for(int i=1;i<=n;i++)
{
if(!vis[i]&&Min>dist[i])
{
Min=dist[i];
idex=i;
}
}
}
printf("%d",dist[t]);
}
int main()
{
scanf("%d %d %d %d",&n,&m,&s,&t);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&o,&p,&q);
addedge(o,p,q);
addedge(p,o,q);
}
dij();
return 0;
}
2.下午三个小时晚上一个半小时
看了讲解堆二叉树、堆优化、优先队列的视频,复习了迪杰斯特拉算法、弗洛伊德算法。