链接:https://ac.nowcoder.com/acm/contest/884/J
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
Your are given an undirect connected graph.Every edge has a cost to pass.You should choose a path from S to T and you need to pay for all the edges in your path. However, you can choose at most k edges in the graph and change their costs to zero in the beginning. Please answer the minimal total cost you need to pay.
The first line contains five integers n,m,S,T,K.
For each of the following m lines, there are three integers a,b,l, meaning there is an edge that costs l between a and b.
n is the number of nodes and m is the number of edges.
An integer meaning the minimal total cost.
示例1
复制
3 2 1 3 1
1 2 1
2 3 2
复制
1
题目大意:给出点的个数n,边的个数m,起点s,终点t,然后你还可以使k条边的权值为0,问从s到e的最短路是多少。
题目思路:这个题题解的DP我没看懂就说一下用图论怎么做吧,我们可以分层建图,层与层之间 权值为0,表示用了一条边(单向边),层内保留原值建图。具体如下图所示:
这样的话从第一层的起点1开始跑,跑到第二层的三需要1,第一层的3需要3,那么就表示使用一条边为0时,路程最短。具体这个题目就模拟一下建图过程就好了,然后用第一层的S作为起点,然后输出第k层E的最小值即可。这里注意分层建图之后,这就时最多 1000*1000个点,边数可能跟会到1e7所以head(链式前向星)数组还有边数组需要开到1e7否则会报错误,具体代码如下:
#include
using namespace std;
typedef long long ll;
const ll INF=1e9+5;
const int maxn=1e7+8;
const double PI=acos(-1);
const ll mod=1e9+7;
ll n,m,s,ee,t;
int head[maxn];
bool vis[maxn];
ll dis[maxn];
struct node{
ll e,next;
ll w;
}edge[maxn];
ll cnt=0;
void addedge1(ll u,ll v,ll w)
{
edge[cnt]=node{v,head[u],w};
head[u]=cnt++;
edge[cnt]=node{u,head[v],w};
head[v]=cnt++;
}
void addedge(ll u,ll v,ll w)
{
edge[cnt]=node{v,head[u],w};
head[u]=cnt++;
}
void spfa(ll st)
{
queueq;for(int i=1;i<=(t+1)*n;i++) vis[i]=false,dis[i]=INF;
q.push(st);vis[st]=true;
dis[st]=0;
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=false;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int e=edge[i].e;
if(dis[e]>dis[u]+edge[i].w)
{
dis[e]=dis[u]+edge[i].w;
if(!vis[e])
{
vis[e]=true;
q.push(e);
}
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%lld%lld%lld%lld%lld",&n,&m,&s,&ee,&t);
for(int i=1;i<=m;i++)
{
ll x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
addedge1(x,y,z);
for(int k=1;k<=t;k++)//层内赋权值
addedge1(k*n+x,k*n+y,z);
ll tempx=x,tempy=y;
for(int k=1;k<=t;k++)//层间负赋权值
{
addedge(tempx,k*n+y,0);
addedge(tempy,k*n+x,0);
tempx=k*n+x;
tempy=k*n+y;
}
}
spfa(s);
ll minl=dis[ee];
printf("%lld\n",dis[t*n+ee]);
return 0;
}
总结:记住分层最短路!!!!