zoukankan      html  css  js  c++  java
  • codevs 1700 施工方案第二季

    1700 施工方案第二季

     

    2012年市队选拔赛北京

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
     
     
    题目描述 Description

    c国边防军在边境某处的阵地是由n个地堡组成的。工兵连受命来到阵地要进行两期施工。

    第一期的任务是挖掘暗道让所有地堡互联互通。现已勘测设计了m条互不相交的暗道挖掘方案,如果这m条暗道都实施挖掘,肯定能达到互联互通的目的。事实上,适当选择其中n-1个方案挖掘,就能实现互联互通,即从每个地堡出发都能到达其他任何一个地堡(允许经过别的地堡)。

    连长精心谋算,在m个设计规划中选取了挖掘总距离最短且能保证互联互通的若干个暗道规划实施了挖掘,完成了第一期的施工任务后又接受了第二期的施工任务,要求选择一个地堡进行扩建改造,使其能向每个地堡提供弹药。为了让弹药供应更及时、更快捷,从改扩建的地堡到最远地堡的距离(称为最远输送距离)应当尽量小。

    你的任务是先求出第一期施工挖掘的总距离,再求改扩建地堡最远输送距离的最小值。

    输入描述 Input Description

    其中第一行是n和m,m>=n
    下面的m行每行3个数xi、yi、zi,表示xi到yi的距离是zi
      zi<1000000且m个距离互不相等

    输出描述 Output Description

    共包含两行,每行一个整数,
    第一行是第一期的挖掘总距离,第二行是最远输送距离的最小值。

    样例输入 Sample Input

    4 5
    1 2 1
    2 3 2
    3 4 3
    4 1 4
    3 1 5

    样例输出 Sample Output

    6
    3

    数据范围及提示 Data Size & Hint

    【样例说明】
    第一期挖掘1到2、2到3和3到4的3条暗道,第二期选择3号地堡进行改扩建,最远输送距离是3
    【数据规模】
    60%的数据 n<10且m<20
    80%的数据 n<1000且m<2000
    100%的数据 n<100000且m<200000

    分类标签 Tags 

     思路:先跑最小生成树,得出第一个答案。

    第二期任务是要求最远距离最小,我们可以很容易的得出以下结论:这个点一定位于这棵树的直径上,并且是这棵树的直径的中点。

    找到这个点后,再跑一个spfa或者dfs,找出离这个点最远的点,这个距离就是答案。

    错因:别忘了开long long。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXNCNT 100010
    #define MAXEDGE 200010
    using namespace std;
    long long ans,ans2;
    int n,m,tot,src,decc,home;
    long long minn=0x7f7f7f7f,mann=0x7f7f7f7f;
    long long dis[MAXNCNT],cap[MAXEDGE*2];
    long long sum1[MAXNCNT],sum2[MAXNCNT];
    int fa[MAXNCNT],dad[MAXNCNT],vis[MAXNCNT];
    int to[MAXEDGE*2],net[MAXEDGE*2],head[MAXNCNT];
    struct nond{ int u,v;long long w; }v[MAXEDGE];
    int abs(int x){ return x>0?x:-x; }
    int cmp(nond a,nond b){ return a.w<b.w; }
    int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); }
    void add(int u,int v,long long w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;cap[tot]=w;net[tot]=head[v];head[v]=tot;
    }
    void spfa(int s){
        queue<int>que;
        memset(vis,0,sizeof(vis));
        memset(dis,0x7f,sizeof(dis));
        dis[s]=0;vis[s]=1;que.push(s);
        while(!que.empty()){
            int now=que.front();
            que.pop();vis[now]=0;
            for(int i=head[now];i;i=net[i])
                if(dis[to[i]]>dis[now]+cap[i]){
                    dis[to[i]]=dis[now]+cap[i];
                    if(!vis[to[i]]){
                        vis[to[i]]=1;
                        que.push(to[i]);
                    }
                }
        }
    }
    void dfs(int now){
        for(int i=head[now];i;i=net[i])
            if(dis[to[i]]==-1){
                dis[to[i]]=dis[now]+cap[i];
                dfs(to[i]);
            }
    }
    void dfs1(int now){
        for(int i=head[now];i;i=net[i])
            if(dad[now]!=to[i]){
                dad[to[i]]=now;
                sum1[to[i]]=sum1[now]+cap[i];
                dfs1(to[i]);
            }
    }
    void dfs2(int now){
        for(int i=head[now];i;i=net[i])
            if(dad[now]!=to[i]){
                dad[to[i]]=now;
                sum2[to[i]]=sum2[now]+cap[i];
                dfs2(to[i]);
            }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d%lld",&v[i].u,&v[i].v,&v[i].w);
        sort(v+1,v+1+m,cmp);
        for(int i=1;i<=n;i++)    fa[i]=i;
        for(int i=1;i<=m;i++){
            int dx=find(v[i].u);
            int dy=find(v[i].v);
            if(dx==dy)    continue;
            fa[dy]=dx;ans+=v[i].w;
            add(v[i].u,v[i].v,v[i].w);
        }
        printf("%lld
    ",ans);
        memset(dis,-1,sizeof(dis));
        decc=1;dis[decc]=0;dfs(decc);
        for(int i=1;i<=n;i++)
            if(dis[i]>dis[decc])    decc=i;
        memset(dis,-1,sizeof(dis));
        dis[decc]=0;dfs(decc);src=decc;
        for(int i=1;i<=n;i++)
            if(dis[i]>dis[decc])    decc=i;
        dfs1(src);memset(dad,0,sizeof(dad));
        dfs2(decc);memset(dad,0,sizeof(dad));
        for(int i=1;i<=n;i++){
            long long little=abs(sum1[i]-sum2[i]);
            if(little<minn){ mann=sum1[i];home=i;minn=little; }
            else if(little==minn)
                if(sum1[i]<mann){ mann=sum1[i];home=i; }
        }
        spfa(home);
        for(int i=1;i<=n;i++)
            if(i!=home&&dis[i]>ans2)    ans2=dis[i];
        cout<<ans2;
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    lufylegendRPG游戏引擎 Yorhom's Game Box
    讨论交流 Yorhom's Game Box
    货币之间的大小写转换
    Unreal3的D3D渲染器部分
    Linxu宿主目录
    用于主题检测的临时日志(b25e234297d442ccba394dd2241308d2 3bfe001a32de4114a6b44005b770f6d7)
    Linux命令 文件命名规则 基础
    C#_GDI_文章粗略整合
    由IDisposable接口导致的using使用 以及using的其他用法
    ADO.NET基础备忘1_SqlConnection SqlCommand SqlDataReader
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/8831065.html
Copyright © 2011-2022 走看看