1. 程式人生 > >noip2012 疫情控制

noip2012 疫情控制

ros close isp algorithm += 多少 範圍 str 不讓

題目描述

H 國有 n 個城市,這 n 個城市用 n-1 條雙向道路相互連通構成一棵樹,1 號城市是首都,也是樹中的根節點。

H 國的首都爆發了一種危害性極高的傳染病。當局為了控制疫情,不讓疫情擴散到邊境城市(葉子節點所表示的城市),決定動用軍隊在一些城市建立檢查點,使得從首都到邊境城市的每一條路徑上都至少有一個檢查點,邊境城市也可以建立檢查點。但特別要註意的是,首都是不能建立檢查點的。

現在,在 H 國的一些城市中已經駐紮有軍隊,且一個城市可以駐紮多個軍隊。一支軍隊可以在有道路連接的城市間移動,並在除首都以外的任意一個城市建立檢查點,且只能在一個城市建立檢查點。一支軍隊經過一條道路從一個城市移動到另一個城市所需要的時間等於道路的長度(單位:小時)。

請問最少需要多少個小時才能控制疫情。註意:不同的軍隊可以同時移動。

輸入輸出格式

輸入格式:

第一行一個整數 n,表示城市個數。

接下來的 n-1 行,每行 3 個整數,u、v、w,每兩個整數之間用一個空格隔開,表示從城市 u 到城市 v 有一條長為 w 的道路。數據保證輸入的是一棵樹,且根節點編號為 1。

接下來一行一個整數 m,表示軍隊個數。

接下來一行 m 個整數,每兩個整數之間用一個空格隔開,分別表示這 m 個軍隊所駐紮的城市的編號。

輸出格式:

共一行,包含一個整數,表示控制疫情所需要的最少時間。如果無法控制疫情則輸出-1。

輸入輸出樣例

輸入樣例#1: 復制
4 
1 2 1 
1 3 2 
3 4 3 
2 
2 2
輸出樣例#1: 復制
3

說明

【輸入輸出樣例說明】

第一支軍隊在 2 號點設立檢查點,第二支軍隊從 2 號點移動到 3 號點設立檢查點,所需時間為 3 個小時。

【數據範圍】

保證軍隊不會駐紮在首都。

對於 20%的數據,2≤ n≤ 10;

對於 40%的數據,2 ≤n≤50,0<w <10^5;

對於 60%的數據,2 ≤ n≤1000,0<w <10^6;

對於 80%的數據,2 ≤ n≤10,000;

對於 100%的數據,2≤m≤n≤50,000,0<w <10^9。

NOIP 2012 提高組 第二天 第三題

———————————————————————————————————————

這道題首先二分其實挺明顯的 數據範圍和最大最小 最小最大這種都是很明顯的二分

考慮二分答案 那麽我們發現如果一只軍隊不能到達首都 那麽我們肯定暴力把他提到最高的位置

這樣肯定是最優的 然後我們再考慮那些可以到首都然後進入首都的某個兒子去幫助別的點的點

我們可以先處理出1的那些親兒子需要軍隊以及還有那些軍隊可以去支援

把他們按需要時間/剩余時間排序之後對應地去處理

當然如果一只軍隊在處理到自己的時候 如果他屬的那個點需要軍隊支援的話 我們肯定優先支援自己所屬的

因為如果他不支援自己的那麽必然後面需要點來支援他 但是後面的點的剩余時間一點比他多 那肯定沒有支援自己來的優qwq

技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using std::max;
using std::sort;
const int M=2e5+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
LL l,r,h[M],mark[M];
int n,m,stk[M],top;
int first[M],cnt;
struct pos{int to,next;LL w;}e[2*M];
void ins(int a,int b,LL w){e[++cnt]=(pos){b,first[a],w}; first[a]=cnt;}
void insert(int a,int b,LL w){ins(a,b,w); ins(b,a,w);}
int vis[M],q[M],ql,qr,dis[M],fa[M];
void dfs(int x){
    int sum=0,h=0;
    for(int i=first[x];i;i=e[i].next){
        int now=e[i].to;
        if(now==fa[x]) continue;
        h++; dfs(now); 
        if(!mark[now]) sum++;
    }
    if(!sum&&h) mark[x]=1;
}
int wh[M],cnt1,cnt2;;
struct Q{int id;LL w;}q1[M],q2[M];
bool cmp(Q a,Q b){return a.w<b.w;}
bool check(LL k){
    //printf("[%lld]\n",k);
    memset(vis,0,sizeof(vis));
    memset(mark,0,sizeof(mark));
    memset(h,0,sizeof(h));
    for(int i=1;i<=top;i++)if(dis[stk[i]]>=k) mark[stk[i]]=1,h[stk[i]]=k;
    for(int x=n;x;x--){
        vis[x]=1;
        for(int i=first[x];i;i=e[i].next){
            int now=e[i].to;
            if(vis[now]||h[x]<e[i].w) continue;
            mark[now]=1; h[now]=max(h[now],h[x]-e[i].w);
        }
    }
    //for(int i=1;i<=n;i++) printf("%lld ",mark[i]); puts("");
    dfs(1);
    
    //for(int i=first[1];i;i=e[i].next) printf("[%d %lld]\n",e[i].to,mark[e[i].to]);puts("");
    cnt1=0; cnt2=0;
    for(int i=first[1];i;i=e[i].next) if(!mark[e[i].to]) q1[++cnt1]=(Q){e[i].to,e[i].w};
    for(int i=1;i<=top;i++)if(dis[stk[i]]<k) q2[++cnt2]=(Q){wh[stk[i]],k-dis[stk[i]]};
    //printf("[%d %d]\n",cnt1,cnt2);
    if(!cnt1) return 1;
    if(cnt2<cnt1) return 0;
    sort(q1+1,q1+1+cnt1,cmp);
    sort(q2+1,q2+1+cnt2,cmp);
    //for(int i=1;i<=cnt1;i++) printf("[%d %lld]\n",q1[i].id,q1[i].w);puts("");
    //for(int i=1;i<=cnt2;i++) printf("[%d %lld]\n",q2[i].id,q2[i].w);puts("");
    int now=1;
    for(int i=1;i<=cnt2;i++){
        if(!mark[q2[i].id]){mark[q2[i].id]=1;continue;}
        while(mark[q1[now].id]&&now<=cnt1) now++;
        if(now==cnt1+1) return 1;
        if(q2[i].w>=q1[now].w){mark[q1[now].id]=1; now++; continue;}
    }
    while(mark[q1[now].id]&&now<=cnt1) now++; if(now==cnt1+1) return 1;
    //puts("");
    return 0;
}
void bfs(){
    ql=qr=1; vis[1]=1; q[ql]=1; ql++;
    for(int i=first[1];i;i=e[i].next){
        int now=e[i].to;
        if(vis[now]) continue;
        fa[now]=1;
        dis[now]=e[i].w;
        q[++qr]=now; vis[now]=1; wh[now]=now;
    }
    while(ql<=qr){
        int x=q[ql++];
        for(int i=first[x];i;i=e[i].next){
            int now=e[i].to;
            if(vis[now]) continue;
            fa[now]=x; wh[now]=wh[x];
            dis[now]=dis[x]+e[i].w;
            q[++qr]=now; vis[now]=1;
        }
    }
}
int main(){
    int x,y,w,mx;
    n=read();
    for(int i=1;i<n;i++) x=read(),y=read(),w=read(),insert(x,y,w),r+=w;
    m=read();
    for(int i=1;i<=m;i++) x=read(),stk[++top]=x;
    bfs();
    //for(int i=1;i<=n;i++) printf("[%d %d %d]\n",fa[i],wh[i],dis[i]);
    mx=r;
    while(l<r){
        LL mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    if(l==mx) printf("-1\n");
    else printf("%lld\n",r);
    return 0;
}
View Code

noip2012 疫情控制