今天接着做最短路的题解。 之前做的题目都是单向图。今天做一个双向图的题目。 还有一个要经过两次函数的题目。 题目如下。
这个题目总的来说。 可以在模板题。那个代码的基础上进行稍微修改一下就可以解决了。 事实上绝大多数最短路的问题都可以依据这个模板进行修改。 我写的模板是有向图的。 然后如果是无相图的话。我采取的方法是输入一个相反的方向的路线存进数组中。如此就可以解决这个问题的。
具体代码就是如下,
#include<bits/stdc++.h>
using namespace std;
int head[10000000],cnt;
long long ans[1000000];
int vis[1000000];
int m,n,s,t;
struct a
{
int to;
int next1;
int fee;
}a[1000000];
void b1(int x,int y,int z)
{
a[++cnt].to=y;
a[cnt].fee=z;
a[cnt].next1=head[x];
head[x]=cnt;
}
int main()
{
cin>>m>>n>>s>>t;
for(int i=1;i<=n;i++)
{
ans[i]=2147483647;
}
ans[s]=0;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
b1(a,b,c);
b1(b,a,c);
}
int s1=s;
while(vis[s1]==0)
{
long long minn=2147483647;
vis[s1]=1;
for(int i=head[s1];i!=0;i=a[i].next1)
{
if(vis[a[i].to]==0&&ans[a[i].to]>ans[s1]+a[i].fee)
{
ans[a[i].to]=ans[s1]+a[i].fee;
}
}
for(int i=1;i<=m;i++)
{
if(ans[i]<minn&&vis[i]==0)
{
minn=ans[i];
s1=i;
}
}
}
cout<<ans[t]<<' ';
}
然后就是另外一题了。 这个题有一点点恶心的地方。先看题目吧。
这个题目恶心的地方就在于他不仅有一个一到多,还有一个多到一。 然后我就利用了一个反向图。来将多到一转化成了一到多,原理就是,如以下这个例子,由c到a的路径为,C到b到a,存到反向图里的话。就会变成ab,这样的话,在反向图中a到c点的最短途径,就是c到a的最短途径。
但是现在就要写两次dijkstra,然后就会有巨大的代码量和调试过程。反正当时是。弄得我怀疑人生。 具体的代码就是下面这个一百多行的。
#include<bits/stdc++.h>
using namespace std;
int head[10000000]={0},cnt=1;
long long ans[1000000];
int vis[1000000];
int m,n;
int head1[10000000]={0},cnt1=1;
long long ans1[1000000];
int vis1[1000000];
int m1,n1;
struct a
{
int to;
int next1;
int fee;
}a[1000000] ,a1[1000000];
void b1(int x,int y,int z)
{
a[++cnt].to=y;
a[cnt].fee=z;
a[cnt].next1=head[x];
head[x]=cnt;
}
void b2(int x,int y,int z)
{
a1[++cnt1].to=y;
a1[cnt1].fee=z;
a1[cnt1].next1=head1[x];
head1[x]=cnt1;
}
int main()
{
cin>>m>>n;
for(int i=2;i<=n;i++)
{
ans[i]=2147483647;
ans1[i]=2147483647;
}
ans[1]=0;
ans1[1]=0;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
b1(a,b,c);
b2(b,a,c);
}
int s1=1;
while(vis[s1]==0)
{
long long minn=2147483647;
vis[s1]=1;
for(int i=head[s1];i!=0;i=a[i].next1)
{
if(vis[a[i].to]==0&&ans[a[i].to]>ans[s1]+a[i].fee)
{
ans[a[i].to]=ans[s1]+a[i].fee;
}
}
for(int i=2;i<=m;i++)
{
if(ans[i]<minn&&vis[i]==0)
{
minn=ans[i];
s1=i;
}
}
}
int s2=1;
while(vis1[s2]==0)
{
long long minn=2147483647;
vis1[s2]=1;
for(int i=head1[s2];i!=0;i=a1[i].next1)
{
if(vis1[a1[i].to]==0&&ans1[a1[i].to]>ans1[s2]+a1[i].fee)
{
ans1[a1[i].to]=ans1[s2]+a1[i].fee;
}
}
for(int i=2;i<=m;i++)
{
if(ans1[i]<minn&&vis1[i]==0)
{
minn=ans1[i];
s2=i;
}
}
}
long long int f=0;
for(int i=2;i<=m;i++)
{
f=f+ans[i]+ans1[i];
}
cout<<f;
}
好了,今天的学习总结就到这里了。