唔 不是很简单的题。。。
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
输入解释:
跟题中例子相同
Sample Output
3
3
6
输出解释:
跟题中例子相同
很神奇的一道题首先。
我们可以找出来 一颗最小的树。
就拿原图举例
实线部分是 最小生成树。然后我们现在要家边使之变成 类次短的 。
对于当前非树边(u,v),设t=lca(u,v),这条非树边可以去尝试更新t-u和t-v(但不包括t)的最短路长度
列出式子也就是
dis[u]=dis[u]+dis[v]+w[u][v]-(dis[u])
所以我们把剩下的边按照 dis[u]+dis[v]+w[u][v]排序
然后 如果 一些点被更新过了 拿第二遍 更新 定然没有第一遍 优 所以 直接跳过就好了。
想象一下 被更新过的点 一定 在一条条链上 也就是曾祖父,祖父,父亲。。神马的
所以 我们这里用并查集维护。求lca的时候 暴力求就好。
所以 要注意的是 此题 卡spfa
要用 dij+heap
第一遍写的 板。
其实挺好理解的 跟dij过程一样用优先队列维护一下
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
//by mars_ch
int n,m;
struct data{
int f,t;
int w,nxt;
}e[200005*2];
struct EDGE
{
int u,v,w;
}ee[2000005];
struct Node
{
int now,weight;
};
int read()
{
char p=getchar();
int s=0;
while(p<'0' || p>'9') p=getchar();
while(p>='0' && p<='9') s=s*10+p-'0',p=getchar();
return s;
}
int nxt[100005];
int first[100005],tot,cnt;
int dis[100005],f[100005],bel[100005];
int fa[100005],pre[2000005],inq[1000005],intree[1000005],deep[1000005];
queue<int> q;
void add(int a,int b,int c)
{
e[tot].f=a,e[tot].t=b;
e[tot].w=c;
e[tot].nxt=first[a];
first[a]=tot++;
}
bool operator < (Node a,Node b){return a.weight>b.weight;}
bool cmp(EDGE a,EDGE b)
{
return a.w<b.w;
}
int find(int x)
{
if(f[x] == x) return x;
else return f[x]=find(f[x]);
}
void dijkstra(){
memset(dis,0x3f,sizeof(dis));
Node jy;
jy.now=1,jy.weight=dis[1]=0;
priority_queue<Node>pq;
pq.push(jy);
while(!pq.empty()){
Node t=pq.top();pq.pop();
for(int i=first[t.now];~i;i=e[i].nxt)
if(dis[e[i].t]>dis[t.now]+e[i].w){
dis[e[i].t]=dis[t.now]+e[i].w;
jy.now=e[i].t;jy.weight=dis[e[i].t];
pre[e[i].t]=i,fa[e[i].t]=t.now;
deep[e[i].t]=deep[t.now]+1;
pq.push(jy);
}
}
}
int main()
{
n=read(),m=read();
memset(first,-1,sizeof(first));
for(int i=1;i<=m;i++){
int a,b,c;
a=read(),b=read(),c=read();
add(a,b,c);
add(b,a,c);
}
dijkstra();
for(int i=1;i<=n;i++)
{
intree[pre[i]]=1;
}
for(int i=0;i<tot;i+=2)
{
if(!intree[i] && !intree[i+1])
{
ee[++cnt].u=e[i].f,ee[cnt].v=e[i].t,ee[cnt].w=dis[e[i].f]+dis[e[i].t]+e[i].w;
}
}
sort(ee+1,ee+cnt+1,cmp);
for(int i=1;i<=n;i++)
{
f[i]=i;
}
for(int i=1;i<=cnt;i++)
{
int u=ee[i].u,v=ee[i].v;
int fx=find(u),fy=find(v);
int lastu=0,lastv=0;
while(fx!=fy)
{
if(deep[fx]<deep[fy]){
swap(fx,fy),swap(u,v),swap(lastu,lastv);
}
if(!bel[u]){
bel[u]=i;
if(lastu) f[lastu]=u;
}
else if(lastu) f[lastu]=fx;
lastu=fx,u=fa[lastu],fx=find(u);
}
}
for(int i=2;i<=n;i++)
{
if(bel[i])printf("%d\n",ee[bel[i]].w-dis[i]);
else printf("-1\n");
}
}