1. 程式人生 > >codevs 1700 施工方案第二季

codevs 1700 施工方案第二季

phy queue fine memset max ttl Go -h _id

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\n",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;
}

codevs 1700 施工方案第二季