cogs 2109. [NOIP2015] 运输计划 WD

★★★   输入文件:transport.in   输出文件:transport.out   简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】


公元 2044 年,人类进入了宇宙纪元。

L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物

流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。

为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?


【输入格式】


第一行包括两个正整数 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 的物流公司完成阶段性工作所需要的最短时间。

【样例输入】

6 3 
1 2 3 
1 6 4 
3 1 7 
4 3 6 
3 5 5 
3 6 
2 5 
4 5

【样例输出】

11

【提示】


所有测试数据的范围和特点如下表所示

请注意常数因子带来的程序效率上的影响。

15年noip的题    简单(错误)思路:spfa+path(稳稳的超时):

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<string>
  7 #include<queue>
  8 
  9 using namespace std;
 10 const int N=300010;
 11 const int maxn=99999;
 12 
 13 int n;
 14 int m;
 15 int now=1;
 16 int dis[N];
 17 int head[N];
 18 int path[N];
 19 bool vis[N];
 20 int bian[N];
 21 int total;
 22 queue<int>q;
 23 
 24 struct node {
 25     int u,v,w,nxt;
 26     int js;
 27 }E[N];
 28 
 29 struct NODE {
 30     int start;
 31     int end;
 32     int Answer;
 33 }Ask[N];
 34 
 35 inline void Add(int u,int v,int w)
 36 {
 37     E[now].u=u;
 38     E[now].v=v;
 39     E[now].w=w;
 40     E[now].js=now;
 41     E[now].nxt=head[u];
 42     head[u]=now;
 43     now++;
 44 }
 45 
 46 inline int read()
 47 {
 48     int x=0,f=1;
 49     char c=getchar();
 50     while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
 51     while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 52     return x*f;
 53 }
 54 
 55 inline void JB(int ST,int EN)
 56 {
 57     int start=ST;
 58     int end=EN;
 59     
 60     while(end!=ST)
 61     {
 62         bian[path[end]]++;
 63         end=E[path[end]].u;
 64     }
 65 }
 66 
 67 inline void chu()
 68 {
 69     for(int i=1;i<=n;i++)
 70         vis[i]=0,dis[i]=maxn,path[i]=0;
 71     while(!q.empty())q.pop();
 72 }
 73 
 74 inline void spfa(int start,int end,int x)
 75 {
 76     chu();
 77     vis[start]=1;
 78     dis[start]=0;
 79     q.push(start);
 80     
 81     while(!q.empty())
 82     {
 83         int top=q.front();
 84         q.pop();
 85         vis[top]=0;
 86         
 87         for(int i=head[top];i!=-1;i=E[i].nxt)
 88         {
 89             if(dis[E[i].v]>dis[E[i].u]+E[i].w)
 90             {
 91                 dis[E[i].v]=dis[E[i].u]+E[i].w;
 92                 path[E[i].v]=E[i].js;
 93                 if(!vis[E[i].v]) q.push(E[i].v);
 94             }
 95         }
 96     }
 97     JB(start,end);
 98     Ask[x].Answer=dis[end];
 99 }
100 
101 inline bool cmp(NODE a,NODE b)
102 {
103     return a.Answer>b.Answer;
104 }
105 
106 int main()
107 {
108     n=read();
109     m=read();
110     
111     for(int i=1;i<=n;i++)
112         head[i]=-1;
113     
114     for(int i=1;i<=n-1;i++)
115     {
116         int u,v,w;
117         u=read();
118         v=read();
119         w=read();
120         Add(u,v,w);
121     }
122     for(int i=1;i<=m;i++)
123     {
124         int start,end;
125         Ask[i].start=read();
126         Ask[i].end=read();
127         spfa(Ask[i].start,Ask[i].end,i);
128     }
129     
130     sort(bian+1,bian+n+1);
131     int YJ=0;
132     for(int i=n;i>=1;i--)
133     {
134         if(bian[i]==m&&E[i].w>E[YJ].w)
135             YJ=i;
136     }
137     
138     sort(Ask,Ask+m+1,cmp);
139     printf("%d",Ask[1].Answer-E[YJ].w);
140     
141     return 0;
142 }

lca+dfs:

  1 #include<set>
  2 #include<queue>
  3 #include<vector>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<algorithm>
  7 
  8 using namespace std;
  9 const int maxn=300005;
 10 
 11 int n,m;
 12 set<int> s1;
 13 set<int> s2;
 14 set<int>::iterator It;
 15 vector<int> G[maxn];
 16 
 17 struct Edge {
 18     int from,to,cap;
 19 };
 20 struct Heapnode {
 21     int id,len;
 22 };
 23 bool operator <(const Heapnode &a,const Heapnode &b) {
 24     return a.len<b.len;
 25 }
 26 bool operator >(const Heapnode &a,const Heapnode &b) {
 27     return a.len>b.len;
 28 }
 29 priority_queue<Heapnode> heap;
 30 struct Query {
 31     int u,v,len,lca;
 32     bool operator < (const Query& rhs) const {
 33         return len>rhs.len;
 34     }
 35 };
 36 Query Q[maxn];
 37 vector<Edge> edges;
 38 int f[maxn][20],dist[maxn],d[maxn],num[maxn];
 39 int readint() {
 40     int x=0;
 41     char ch=getchar();
 42     while(ch<'0'||ch>'9') ch=getchar();
 43     while(ch>='0'&&ch<='9') {
 44         x=x*10+ch-'0';
 45         ch=getchar();
 46     }
 47     return x;
 48 }
 49 void dfs(int u,int fa,int sum) {
 50     dist[u]=sum;
 51     d[u]=d[fa]+1;
 52     f[u][0]=fa;
 53     for(int i=1; i<20; i++)
 54         f[u][i]=f[f[u][i-1]][i-1];
 55     for(int i=0; i<G[u].size(); i++) {
 56         if(edges[G[u][i]].to!=fa) dfs(edges[G[u][i]].to,u,sum+edges[G[u][i]].cap);
 57         else num[u]=G[u][i];
 58     }
 59 }
 60 void Lca1(int &u,int &v,int cnt) {
 61     int su=u,sv=v;
 62     if(d[u]>d[v]) {
 63         u^=v;
 64         v^=u;
 65         u^=v;
 66     }
 67     int dis=d[v]-d[u];
 68     int ret=dist[v]+dist[u];
 69     for(int i=19; i>=0; i--) {
 70         if((dis>>i)&1) v=f[v][i];
 71     }
 72     for(int i=19; i>=0; i--) {
 73         if(f[u][i]!=f[v][i]) {
 74             u=f[u][i];
 75             v=f[v][i];
 76         }
 77     }
 78     if(u!=v) {
 79         u=f[u][0];
 80         v=f[v][0];
 81     }
 82     ret-=2*dist[u];
 83     Q[cnt].u=su;
 84     Q[cnt].v=sv;
 85     Q[cnt].len=ret;
 86     Q[cnt].lca=u;
 87 }
 88 void Add_Edge1(int u,int k) {
 89     if(u==Q[k].lca) return;
 90     s1.insert(num[u]);
 91     heap.push((Heapnode) {
 92         num[u],edges[num[u]].cap
 93     });
 94     Add_Edge1(edges[num[u]].to,k);
 95 }
 96 void Add_Edge(int u,int k) {
 97     if(u==Q[k].lca) return;
 98     s2.insert(num[u]);
 99     Add_Edge(edges[num[u]].to,k);
100 }
101 int main() {
102     freopen("transport.in","r",stdin);
103     freopen("transport.out","w",stdout);
104     n=readint();
105     m=readint();
106     int from,to,cap;
107     for(int i=1; i<n; i++) {
108         from=readint();
109         to=readint();
110         cap=readint();
111         edges.push_back((Edge) {
112             from,to,cap
113         });
114         edges.push_back((Edge) {
115             to,from,cap
116         });
117         G[from].push_back(edges.size()-2);
118         G[to].push_back(edges.size()-1);
119     }
120     dfs(1,0,0);
121     int u,v,len;
122     for(int i=0; i<m; i++) {
123         u=readint();
124         v=readint();
125         Lca1(u,v,i);
126     }
127     sort(Q,Q+m);
128     int ans=0;
129     s1.clear();
130     s2.clear();
131     Add_Edge1(Q[0].u,0);
132     Add_Edge1(Q[0].v,0);
133     ans=Q[0].len-(heap.top()).len;
134     for(int i=1; i<m; i++) {
135         if(ans>=Q[i].len) break;
136         ans=Q[i].len;
137         Add_Edge(Q[i].u,i);
138         Add_Edge(Q[i].v,i);
139         It=s1.begin();
140         for(It; It!=s1.end();) {
141             int cnt=(*It);
142             It++;
143             if(!s2.count(cnt)) {
144                 s1.erase(cnt);
145             }
146         }
147         s2.clear();
148         if(s1.empty()) break;
149         while(!s1.count(heap.top().id)) {
150             heap.pop();
151         }
152         if(Q[0].len-(heap.top()).len>=ans) break;
153         ans=Q[0].len-(heap.top()).len;
154     }
155     printf("%d",ans);
156     return 0;
157 }
原文地址:https://www.cnblogs.com/lyqlyq/p/6899844.html