1576: [Usaco2009 Jan]安全路经Travel
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1434 Solved: 507
[ Submit][ Status][ Discuss]
Description
Input
* 第一行: 两个空格分开的数, N和M
* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i
Output
* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.
Sample Input
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
Sample Output
3
3
6
输出解释:
跟题中例子相同
3
6
输出解释:
跟题中例子相同
HINT
Source
刚开始我傻了
竟然还想着每个点跑两次spfa
忘记还要*n了
我觉得他讲的挺好的
我也没什么好讲的QAQ
类似的题目可以看一下51nod 1076 2条不相交的路径
具体做法方面
我跑了8000ms
听说是spfa的原因
不加slf优化还会T
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=1e5+18,M=1e5*2+18,len=1e6;
struct node
{
int from,to,next,c;
}e[M*2];
struct edgt
{
int from,to,c;
}ee[M*2];
int first[N],bo[N],dis[N],qu[len+6],ans[N];
int cnt=0;
int fa[N],f[N];
void swap(int &a,int &b)
{
int temp=b;b=a;a=temp;
}
bool cmp(edgt a,edgt b)
{
return a.c<b.c;
}
int get(int v)
{
return f[v]==v?v:f[v]=get(f[v]);
}
inline void insert(int u,int v,int c)
{
e[++cnt]=(node){u,v,first[u],c};first[u]=cnt;
e[++cnt]=(node){v,u,first[v],c};first[v]=cnt;
}
void spfa()
{
memset(dis,127,sizeof(dis));
int head=1,tail=2;
qu[1]=1;dis[1]=0;bo[1]=1;
while(head!=tail)
{
int rr=qu[head++];if(head==len) head=0;
bo[rr]=0;
for(int k=first[rr];k;k=e[k].next)
if(dis[e[k].to]>dis[rr]+e[k].c)
{
dis[e[k].to]=dis[rr]+e[k].c;
fa[e[k].to]=rr;
if(!bo[e[k].to])
{
bo[e[k].to]=1;
if(dis[e[k].to]<dis[qu[head]])
{
head--;if(head<0) head=len-1;
qu[head]=e[k].to;
}
else
{
qu[tail++]=e[k].to;if(tail==len) tail=0;
}
}
}
}
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
int u,v,c;
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&u,&v,&c);
insert(u,v,c);
}
spfa();
int tot=0;
for(int i=1;i<=cnt;i++)
{
int u=e[i].from,v=e[i].to,c=e[i].c;
if(fa[u]==v||fa[v]==u) continue;
ee[++tot]=(edgt){u,v,c+dis[u]+dis[v]};
}
std::sort(ee+1,ee+1+tot,cmp);
memset(ans,-1,sizeof(ans));
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=tot;i++)
{
int u=ee[i].from,v=ee[i].to,c=ee[i].c;
u=get(u),v=get(v);
while(u!=v)
{
if(dis[u]<dis[v]) swap(u,v);
ans[u]=c-dis[u];
int faa=get(fa[u]);
f[u]=faa;
u=faa;
}
}
for(int i=2;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}