P2934 [USACO09JAN]安全出行

图论瞎搞......

solution:

按例化简:给定一个无向图,保证单源最短路唯一,求每个点到1号点的最短路最后一条边被封锁的情况下的最短路

乍一看,应该是次短路,但是稍微用脚趾头想想都能发现不是次短路.....

然后就乱搞了一发。秉承着我们的口号

暴力碾标算,n方过百万

我试着搞了一发暴力:先求出最短路径树(很重要),然后对于每一个点的父亲(前一个节点)进行dij拓展,不走被封的边,然后遇到目标点就退出(思路来源:旅行者

然后我发现,不仅仅会T,甚至这个思路就是错的!!!

1、为什么会T:旅行者那题相当于只找一个最短边权当做最短路,因此dij的拓展过程可以认为是O(1)的;

2、为什么会wa:来看样例:

我弄出来的最短路径树是这样的:

根据以上思路,只需要求出dis(最短路),还有从父亲节点拓展的dis,加起来即可。

但是,当走到2,拓展4的时候:拓展的非树边和之前的最短路加起来,变成了7!?

但是,如果换一条路走,答案应该是6......

所以,这个思路到此终结(我170+lines的代码啊!!!!)

正解:(对,没错,这里才开始正解)

首先,最短路径树的思路要保留,这里有一个比较玄学的式子:

min(dis(u,v)(边权)+dis(u)-dis(v)+dis(v));

要求根到f的路径径,只需要知道根到u的最短路-根到f的最短路(也就是f到u的一条路径)加上根到v的最短路,再加上u到v的边权,这样就完成了一次拓展。

于是,就维护这个式子,用并查集维护联通(据机房大佬说这是并查集缩变233)

  • 把所有非树边 记录下来
  • 枚举点
  • 更新式子
  • 维护连通
  • 进行n-1次

就是这样....据说spfa会被卡?本人专门卡各种卡spfa.....

注意一下,要判断无解.....

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,m;
inline int read()
{
    int x=0,f=1;char s=getchar();
    while(s>‘9‘||s<‘0‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s<=‘9‘&&s>=‘0‘){x=x*10+s-‘0‘;s=getchar();}
    return f*x;
}
struct edge
{
    int to,next,dis;
}e[maxn];
int cnt,head[maxn];
inline void addedge(int from,int to,int dis)
{
    e[++cnt].next=head[from];
    e[cnt].to=to;
    e[cnt].dis=dis;
    head[from]=cnt;
}
int fa[maxn];
int dis[maxn];
struct cmp
{
    bool operator ()(int a,int b)
    {
        return dis[a]>dis[b];
    }
};
priority_queue <int,vector<int>,cmp> q;
int vis[maxn];
inline void spfa(int s)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=0x7fffffff;
        vis[i]=0;
    }
    vis[s]=1;
    dis[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int u=q.top();
        q.pop();
        vis[u]=0;
        for(register int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].dis)
            {
                dis[v]=dis[u]+e[i].dis;
                fa[v]=u;
                if(vis[v]==0)
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

struct tree
{
    int u,v,w;
}a[maxn];
bool cmp(tree a,tree b)
{
    return a.w<b.w;
}
int f[maxn],ans[maxn];
int num;
int find(int x)
{
    if(f[x]==x)
    return x;
    return f[x]=find(f[x]);
}
void solve(tree x)
{
    int u=x.u,v=x.v,t=x.w;
    while(find(u)!=find(v))
    {
        num++;
        if(dis[find(u)]<dis[find(v)])
        swap(u,v);
        ans[find(u)]=min(ans[find(u)],t-dis[find(u)]);
        u=f[find(u)]=fa[find(u)];
    }
}
int tot;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        x=read();y=read();z=read();//scanf("%d%d%d",&x,&y,&z);
        addedge(x,y,z);
        addedge(y,x,z);
    }
    spfa(1);
    for(int i=2;i<=cnt;i+=2)
    {
        int u=e[i].to;
        int v=e[i-1].to;;
        if(u!=fa[v]&&v!=fa[u])
        {
            a[++tot].u=u;
            a[tot].v=v;
            a[tot].w=e[i].dis+dis[u]+dis[v];
        }
    }

    sort(a+1,a+1+tot,cmp);
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
        ans[i]=2147483647;
    }
    for(int i=1;i<=tot&&num<n-1;i++)
    {
        solve(a[i]);
    }
    for(int i=2;i<=n;i++)
    {
        if(ans[i]!=2147483647)
        printf("%d\n",ans[i]);
        else
        printf("-1\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ajmddzp/p/11441776.html

时间: 2024-11-12 03:42:34

P2934 [USACO09JAN]安全出行的相关文章

[USACO09JAN]安全出行Safe Travel

[USACO09JAN]安全出行Safe Travel 题目描述 Gremlins have infested the farm. These nasty, ugly fairy-like creatures thwart the cows as each one walks from the barn (conveniently located at pasture_1) to the other fields, with cow_i traveling to from pasture_1 t

[USACO09JAN]安全出行Safe Travel(最短路径树)

传送门 求对于每个点删掉1到他的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1到他的最短路的长度. 即:最短路径树:图中的源点到所有结点的最短路径构成的树. 最短路径树在dijkstra过程中就可以求出来,因为这个过程就相当于走一棵树. 然后就是选入杂边,对于一条杂边<u,v>,它加入后会形成一个环,这个环上所有的点除了lca都可以被这条杂边更新,即这些点删去它上面那条边后是可以走杂边的,但lca删去上面那条边后图就不连通了. 那么 disnew[x]=dis[u]+dis[v

9.8解题报告

9.8解题报告 前50min写完了三个题的暴力,但是暴力的正确性不高qwq. 没有造数据绝对不是因为我懒. 然后开始想正解,T1想了一个O(n)的方法,但是写代码的时候bug太多,所以调试花了将近2个小时. 然后剩下的两个题就没大看. 距考试结束还有20min时,总感觉自己的T1有bug,所以15min写完了n*√n的,交上了这个. 所以最后完美的炸掉了考试. T1 100    T2 20    T3 10 qwq浪费时间的人绝对不是我. T1 #include<cmath> #includ

AppCan+滴滴:为APP一键接入O2O出行服务

移动互联.大数据.云计算让信息流趋于透明,推动"分享"经济的发展,让人人.物物.人与物的连接更加紧密.智能.APP作为移动智能生活的触角,正在成为"连接"的最重要介质,将衣食住行.工作娱乐聚合在一起,云端融合.跨界聚合的新商业形态正在展现. 近日,国内领先的Hybrid混合开发平台AppCan与滴滴深度合作,全面接入滴滴开放平台,让开发者为APP一键接入滴滴出行服务.具体说来,AppCan开发者不需要使用复杂的原生(Android\iOS)能力,仅需前端JavaSc

云时代的多彩出行——航美集团连接旅途中一切美好

尽管"十一黄金周"已经过去,大多数人依然沉浸在假期旅行带来的美好回忆中.旅行是一件让人身心愉悦的事情,但一次美好的旅行往往要从一次无聊的长途客运或者火车开始.特别是在互联网时代,不论是乘坐长途客车还是火车,坐在座位上就意味着你要告别电视.电脑以及我们已经脱离不开的网络. 如何消除旅途过程中,长途客运.火车这种网络不畅的信息孤岛,让长途旅行变得更加美好?这是航美集团一直以来致力解决的问题.航美集团通过提供免费的无线网络服务与媒体内容,让乘客在乘坐长途客车.火车的过程不再无聊.在"

VR旅游要爆火?先倒霉的是导游还是出行平台

VR的火爆显而易见,无论是高高在上的巨头,还是初创业的"小虾米",都想在VR行业分一杯羹.无论是硬件,还是内容,都不乏参与者.但看多了各种包装地光鲜亮丽的VR软硬件和概念,却不得不承认一个事实:目前的VR行业依然只是虚火旺盛,实质不足. 不过总是会有抢跑的,相比VR电影.VR购物.VR眼镜等,VR旅游看起来有爆火的节奏.而在爆火之后,最先倒霉的是导游行业还是出行平台? VR旅游爆火!内容成关键 5月底,嘉峪关君和国际旅行社联手上海抓马数字科技有限公司,在嘉峪关市成立全国第一家线下&qu

东大OJ1171题:ACMER的出行计划

Problem Description 众所周知,ACMER经常要到全国各地去参加各种比赛. 每当要出去比赛的时候,我们先要制定一个出行计划,比如说我们是坐飞机还是坐火车,从哪里坐到哪里等等. 现在给你一副路线图,请你制定一个合理的出行计划,由于经费有限,规定最多只能坐k次飞机. Input 第一行给出一个T,表示有T组数据,之后每组数据第一行分别给出n,m,k(n为点数,分别编号为1-n.m为单向边数) 接下来的m行每行分别给出u,v,w,x(u和v分别为两端点编号,方向为u->v.w为费用.

结对项目—地铁出行路线规划

结对项目—地铁出行路线规划 我的搭档:陈鸿超 14061216 https://github.com/ChengFR/PairProgramming_SubwayRoute- 会在十一期间发布新版本 结对编程体会: 结对编程的优点: 站在软件开发的角度,两个人共同面对同一台电脑进行开发,无论是效率还是软件质量都要超过一个人进行开发的情况. 对于还处于学习阶段的年轻软件开发者来说,结对编程是一个很好的互相学习的机会 结对编程时动力.责任感更强 结对编程的缺点: 对于我们来说,寻找两个人共同的时间进

地铁出行路线规划程序

工程:实现一个帮助进行地铁出行路线规划的命令行程序. 使用PSP表格记录预估将在程序的各个模块的开发上耗费的时间. PSP 2.1 Personal Software Process Stages Time Planning 计划 · Estimate · 估计这个任务需要多少时间 10h Development 开发 · Analysis · 需求分析 (包括学习新技术) 30min · Design Spec · 生成设计文档 无 · Design Review · 设计复审 (和同事审核设