1. 程式人生 > >NOIP2015-D2T3運輸計劃

NOIP2015-D2T3運輸計劃

耗時 algorithm 影響 double per 描述 string esp ==

題目背景

公元 2044 年,人類進入了宇宙紀元。

題目描述

L 國有 n 個星球,還有 n-1 條雙向航道,每條航道建立在兩個星球之間,這 n-1 條航道連通了 L 國的所有星球。

小 P 掌管一家物流公司,該公司有很多個運輸計劃,每個運輸計劃形如:有一艘物

流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球去。顯然,飛船駛過一條航道 是需要時間的,對於航道 j,任意飛船駛過它所花費的時間為 tj,並且任意兩艘飛船之 間不會產生任何幹擾。

為了鼓勵科技創新,L 國國王同意小 P 的物流公司參與 L 國的航道建設,即允許小 P 把某一條航道改造成蟲洞,飛船駛過蟲洞不消耗時間。

在蟲洞的建設完成前小 P 的物流公司就預接了 m 個運輸計劃。在蟲洞建設完成後, 這 m 個運輸計劃會同時開始,所有飛船一起出發。當這 m 個運輸計劃都完成時,小 P 的 物流公司的階段性工作就完成了。

如果小 P 可以自由選擇將哪一條航道改造成蟲洞,試求出小 P 的物流公司完成階段 性工作所需要的最短時間是多少?

輸入輸出格式

輸入格式:

輸入文件名為 transport.in。

第一行包括兩個正整數 n、m,表示 L 國中星球的數量及小 P 公司預接的運輸計劃的數量,星球從 1 到 n 編號。

接下來 n-1 行描述航道的建設情況,其中第 i 行包含三個整數 ai, bi 和 ti,表示第

i 條雙向航道修建在 ai 與 bi 兩個星球之間,任意飛船駛過它所花費的時間為 ti。

接下來 m 行描述運輸計劃的情況,其中第 j 行包含兩個正整數 uj 和 vj,表示第 j個 運輸計劃是從 uj 號星球飛往 vj 號星球。

輸出格式:

輸出 共1行,包含1個整數,表示小P的物流公司完成階段性工作所需要的最短時間。

輸入輸出樣例

輸入樣例#1:
6 3 
1 2 3 
1 6 4 
3 1 7 
4 3 6 
3 5 5 
3 6 
2 5 
4 5
輸出樣例#1:
11

說明

所有測試數據的範圍和特點如下表所示

技術分享

請註意常數因子帶來的程序效率上的影響。


這題首先用的是二分+暴力判斷

二分答案然後把大於m的樹鏈一一枚舉,找可行的邊取交集

80分

技術分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4
#include<cstring> 5 #define MAXN 300005 6 #define LOG 20 7 #define pii pair<int,int> 8 using namespace std; 9 int first[MAXN],Next[MAXN*2],to[MAXN*2],W[MAXN*2],cnt; 10 int n,m; 11 int fa[LOG][MAXN],d[LOG][MAXN],dep[MAXN]; 12 int mid; 13 struct Lian{ 14 int x,y,lca; 15 int Val; 16 friend bool operator < (const Lian &p1,const Lian &p2){ 17 return (p1.Val<p2.Val); 18 } 19 friend bool operator > (const Lian &p1,const Lian &p2){ 20 return !(p1.Val<p2.Val); 21 } 22 } s[MAXN]; 23 void Add(int x,int y,int w){ 24 Next[++cnt]=first[x]; first[x]=cnt; to[cnt]=y; W[cnt]=w; 25 Next[++cnt]=first[y]; first[y]=cnt; to[cnt]=x; W[cnt]=w; 26 // double edge 27 } 28 void dfs(int x){ 29 for(int e=first[x];e;e=Next[e]){ 30 int y=to[e],w=W[e]; 31 if(y==fa[0][x]){ 32 continue; 33 } 34 fa[0][y]=x; 35 d[0][y]=w; 36 dep[y]=dep[x]+1; 37 dfs(y); 38 } 39 } 40 pii LCA(int x,int y){ 41 if(dep[x]<dep[y]){ 42 swap(x,y); 43 } 44 int L=0; 45 for(int k=dep[x]-dep[y],p=0;k;k>>=1,p++){ 46 if(k&1){ 47 L+=d[p][x]; 48 x=fa[p][x]; 49 } 50 } 51 if(x==y){ 52 return make_pair(L,x); 53 } 54 for(int k=LOG-1;k>=0;k--){ 55 if(fa[k][x]!=fa[k][y]){ 56 L+=d[k][x]; 57 L+=d[k][y]; 58 x=fa[k][x]; 59 y=fa[k][y]; 60 } 61 } 62 return make_pair(L+d[0][x]+d[0][y],fa[0][x]); 63 } 64 int b[MAXN]; 65 bool check(){ 66 memset(b,0,sizeof(b)); 67 Lian t;t.Val=mid; 68 int Pos=upper_bound(s+1,s+m+1,t)-s; 69 if(Pos>m){ 70 return 1; 71 } 72 int num=m-Pos+1; 73 for(int i=Pos;i<=m;i++){ 74 int lc=s[i].x,rc=s[i].y; 75 int lca=s[i].lca,L=s[i].Val; 76 while(lc!=lca){ 77 if(L-d[0][lc]<=mid){ 78 b[lc]++; 79 if(b[lc]>=num){ 80 return 1; 81 } 82 } 83 lc=fa[0][lc]; 84 } 85 while(rc!=lca){ 86 if(L-d[0][rc]<=mid){ 87 b[rc]++; 88 if(b[rc]>=num){ 89 return 1; 90 } 91 } 92 rc=fa[0][rc]; 93 } 94 } 95 return 0; 96 } 97 int main() 98 { 99 // freopen("T1.in","r",stdin); 100 // freopen("my.out","w",stdout); 101 scanf("%d%d",&n,&m); 102 for(int i=1;i<n;i++){ 103 int x,y,w; 104 scanf("%d%d%d",&x,&y,&w); 105 Add(x,y,w); 106 } 107 dep[1]=1; 108 dfs(1); 109 for(int k=1;k<LOG;k++){ 110 for(int i=1;i<=n;i++){ 111 fa[k][i]=fa[k-1][fa[k-1][i]]; 112 d[k][i]=d[k-1][i]+d[k-1][fa[k-1][i]]; 113 } 114 } 115 for(int i=1;i<=m;i++){ 116 scanf("%d%d",&s[i].x,&s[i].y); 117 pii t=LCA(s[i].x,s[i].y); 118 s[i].lca=t.second; 119 s[i].Val=t.first; 120 } 121 sort(s+1,s+m+1); 122 // for(int i=1;i<=n;i++){ 123 // mid=s[i].Val; 124 // if(check()){ 125 // printf("1\n"); 126 // } 127 // else{ 128 // printf("0\n"); 129 // } 130 // } 131 int L=1,R=s[m].Val; 132 while(L<R-1){ 133 mid=(L+R)/2; 134 if(check()){ 135 R=mid; 136 } 137 else{ 138 L=mid; 139 } 140 } 141 mid=L; if(check()){ 142 printf("%d\n",L); 143 } 144 else{ 145 printf("%d\n",R); 146 } 147 return 0; 148 }
View Code

實際上判斷用樹上差分提高效率即可AC

技術分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define MAXN 300005
  6 #define LOG 20
  7 #define pii pair<int,int>
  8 using namespace std;
  9 int first[MAXN],Next[MAXN*2],to[MAXN*2],W[MAXN*2],cnt;
 10 int n,m;
 11 int fa[LOG][MAXN],d[LOG][MAXN],dep[MAXN];
 12 int mid;
 13 struct Lian{
 14     int x,y,lca;
 15     int Val;
 16     friend bool operator < (const Lian &p1,const Lian &p2){
 17         return (p1.Val<p2.Val);
 18     }
 19     friend bool operator > (const Lian &p1,const Lian &p2){
 20         return !(p1.Val<p2.Val);
 21     }
 22 } s[MAXN];
 23 void Add(int x,int y,int w){
 24     Next[++cnt]=first[x]; first[x]=cnt; to[cnt]=y; W[cnt]=w;
 25     Next[++cnt]=first[y]; first[y]=cnt; to[cnt]=x; W[cnt]=w;
 26     // double edge
 27 }
 28 void dfs(int x){
 29     for(int e=first[x];e;e=Next[e]){
 30         int y=to[e],w=W[e];
 31         if(y==fa[0][x]){
 32             continue;
 33         }
 34         fa[0][y]=x;
 35         d[0][y]=w;
 36         dep[y]=dep[x]+1;
 37         dfs(y);
 38     }
 39 }
 40 pii LCA(int x,int y){
 41     if(dep[x]<dep[y]){
 42         swap(x,y);
 43     }
 44     int L=0;
 45     for(int k=dep[x]-dep[y],p=0;k;k>>=1,p++){
 46         if(k&1){
 47             L+=d[p][x];
 48             x=fa[p][x];
 49         }
 50     }
 51     if(x==y){
 52         return make_pair(L,x);
 53     }
 54     for(int k=LOG-1;k>=0;k--){
 55         if(fa[k][x]!=fa[k][y]){
 56             L+=d[k][x];
 57             L+=d[k][y];
 58             x=fa[k][x];
 59             y=fa[k][y];
 60         }
 61     }
 62     return make_pair(L+d[0][x]+d[0][y],fa[0][x]);
 63 }
 64 int b[MAXN];
 65 int num;
 66 int find(int x){
 67     int ret=0;
 68     for(int e=first[x];e;e=Next[e]){
 69         int y=to[e];
 70         if(y==fa[0][x]) continue;
 71         ret=max(ret,find(y));
 72         b[x]+=b[y];
 73     }
 74     if(b[x]==num){
 75         ret=max(ret,d[0][x]);
 76     }
 77     return ret;
 78 }
 79 bool check(){
 80     memset(b,0,sizeof(b));
 81     Lian t;t.Val=mid;
 82     int Pos=upper_bound(s+1,s+m+1,t)-s;
 83     if(Pos>m){
 84         return 1;
 85     }
 86     num=m-Pos+1;
 87     for(int i=Pos;i<=m;i++){
 88         int lc=s[i].x,rc=s[i].y;
 89         int lca=s[i].lca,L=s[i].Val;
 90         b[lc]++,b[rc]++;
 91         b[lca]-=2;
 92     }
 93     int temp=find(1);
 94     return (s[m].Val-temp<=mid);
 95 }
 96 int main()
 97 {
 98  //   freopen("T1.in","r",stdin);
 99 //    freopen("my.out","w",stdout);
100     scanf("%d%d",&n,&m);
101     for(int i=1;i<n;i++){
102         int x,y,w;
103         scanf("%d%d%d",&x,&y,&w);
104         Add(x,y,w);
105     }
106     dep[1]=1;
107     dfs(1);
108     for(int k=1;k<LOG;k++){
109         for(int i=1;i<=n;i++){
110             fa[k][i]=fa[k-1][fa[k-1][i]];
111             d[k][i]=d[k-1][i]+d[k-1][fa[k-1][i]];
112         }
113     }
114     for(int i=1;i<=m;i++){
115         scanf("%d%d",&s[i].x,&s[i].y);
116         pii t=LCA(s[i].x,s[i].y);
117         s[i].lca=t.second;
118         s[i].Val=t.first;
119     }
120     sort(s+1,s+m+1);
121 //    for(int i=1;i<=n;i++){
122 //        mid=s[i].Val;
123 //        if(check()){
124 //            printf("1\n");
125 //        }
126 //        else{
127 //            printf("0\n");
128 //        }
129 //    }
130     int L=0,R=s[m].Val;
131     while(L<R-1){
132         mid=(L+R)/2;
133         if(check()){
134             R=mid;
135         }
136         else{
137             L=mid;
138         }
139     }
140     mid=L; if(check()){
141         printf("%d\n",L);
142     }
143     else{
144         printf("%d\n",R);
145     }
146     return 0;
147 }
View Code

NOIP2015-D2T3運輸計劃