您的位置:首页 > 其它

NOIP 2013 货车运输 题解过程

2016-10-13 08:09 375 查看
今天做了NOIP 2013 的货车运输。 

刚开始一看题目。

**题目描述 Description 

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。 

输入描述 Input Description 

第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。 

接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。 

接下来一行有一个整数 q,表示有 q 辆货车需要运货。 

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。 

输出描述 Output Description 

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。 

样例输入 Sample Input 

4 3 

1 2 4 

2 3 3 

3 1 1 



1 3 

1 4 

1 3 

样例输出 Sample Output 



-1 



数据范围及提示 Data Size & Hint 

对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000; 

对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000; 

对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

首先想到的是并查集维护的最大生成树。 

然后对于每一次询问,一条边一条边的加,直到加到某一条边后能导致所询问的两点能够联通;因为已经按照边权从小到大排序过,所以现在加的边肯定是通路里面权值最小的边。输出此边即可。

不难看出,这种方法是正确的,但是对于后40%的数据会TLE。 

(后面有60分的代码,这种做法比较好写,适合骗分) 

所以,我们只进行一次最大生成树,之后用倍增的方法求每次询问的两点的LCA 查找过程中维护道路上的最小值,最后输出即可。复杂度为O(mlogn)的。

60分代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<string>
#include<bitset>
#include<iomanip>
#include<deque>
#define INF 1000000000
#define fi first
#define se second
#define N 100005
#define P 1000000007
#define debug(x) cerr<<#x<<"="<<x<<endl
#define MP(x,y) make_pair(x,y)
using namespace std;
int n,m,s,ti,c;
int h
,v
,next
,p=0,d
,f
;
inline int get_num()
{
int num = 0;
char c;
bool flag = false;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
if (c == '-') flag = true;
else num = c - '0';
while (isdigit(c = getchar()))
num = num * 10 + c - '0';
return (flag ? -1 : 1) * num;
}
struct re
{
int x,y,bh,qz;
} q
;
void mem()
{
for(int i=1;i<=N;i++)
{
f[i]=i;
}
}
int find(int x)
{
return f[x]==x ? x:f[x]=find(f[x]);
}
void add(int a,int b,int c)
{
p++;
q[p].x=a;
q[p].y=b;
q[p].bh=p;
q[p].qz=c;
}
bool cmp(const struct re a,const struct re b)
{
return a.qz>b.qz;
}
int main()
{
n=get_num();
m=get_num();
for(int i=1;i<=m;i++)
{
int qqq,w,e;
qqq=get_num();w=get_num();e=get_num();
add(qqq,w,e);
add(w,qqq,e);
}
sort(q+1,q+p+1,cmp);
/*for(int i=1;i<=m*2;i++)
{
cout<<q[i].qz<<" ";
}*/
c= get_num();
for(int i=1;i<=c;i++)
{
int qq,w,ans=2147483647;
bool vv=0;
qq=get_num();w=get_num();
mem();
for(int j=1;j<=p;j++)
{
if(find(q[j].x)!=find(q[j].y))
{
f[f[q[j].x]]=f[q[j].y];
//ans=min(ans,q[j].qz);
}
if(find(qq)==find(w))
{
printf("%d\n",q[j].qz);
vv=1;
break;
}
}
if(!vv)
{
printf("-1\n");
}
}
return 0;
}

满分LCA 做法:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<string>
#include<bitset>
#include<iomanip>
#include<deque>
#define INF 1000000000
#define fi first
#define se second
#define N 100005
#define P 1000000007
#define debug(x) cerr<<#x<<"="<<x<<endl
#define MP(x,y) make_pair(x,y)
using namespace std;
int n,m,s,ti,c;
int h
,v
,next
,p=0,d
,f
,w
,l
,j
[15],ww
[15],deep
;
bool vv
;
inline int get_num()
{
int num = 0;
char c;
bool flag = false;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
if (c == '-') flag = true;
else num = c - '0';
while (isdigit(c = getchar()))
num = num * 10 + c - '0';
return (flag ? -1 : 1) * num;
}
struct re
{
int x,y,bh,qz;
} q
;
int find(int x)
{
return f[x]==x ? x:f[x]=find(f[x]);
}
void add(int a,int b,int c)
{
p++;
v[p]=b;
w[p]=c;
next[p]=h[a];
h[a]=p;
l[p]=a;
}
void addd(int a,int b,int c)
{
p++;
q[p].x=a;
q[p].y=b;
q[p].bh=p;
q[p].qz=c;
}
bool cmp(const struct re a,const struct re b)
{
return a.qz>b.qz;
}
void dfs(int x,int s)
{
deep[x]=s;
for(int i=1;(1<<i)<s;i++)
{
j[x][i]=j[j[x][i-1]][i-1];
ww[x][i]=min(ww[x][i-1],ww[j[x][i-1]][i-1]);
//cout<<x<<" "<<i<<" :"<<ww[x][i]<<endl;
}
int p=h[x];
while(p)
{
if(vv[v[p]])
{
p=next[p];
continue;
}
vv[v[p]]=1;
j[v[p]][0]=x;
ww[v[p]][0]=w[p];
dfs(v[p],s+1);

}
return;
}
int just_doit(int x,int y)
{
int ans=2147483647;
if(deep[y]>deep[x])
{
int tt=x;
x=y;
y=tt;
}
for(int i=15;i>=0;i--)
{
if(deep[x]-(1<<i)>=deep[y])
{
ans=min(ans,ww[x][i]);
x=j[x][i];
}
}
if(x==y)
{
return ans;
}
for(int i=15;i>=0;i--)
{

4000
if(deep[x]-(1<<i)>=1&&j[x][i]!=j[y][i])
{
ans=min(ans,ww[x][i]);
ans=min(ans,ww[y][i]);
x=j[x][i];
y=j[y][i];
}
}
ans=min(ans,ww[x][0]);
ans=min(ans,ww[y][0]);
return ans;
}
int main()
{
n=get_num();
m=get_num();
for(int i=1;i<=m;i++)
{
int qqq,w,e;
qqq=get_num();w=get_num();e=get_num();
addd(qqq,w,e);
addd(w,qqq,e);
}
sort(q+1,q+p+1,cmp);
for(int i=1;i<=n;i++) f[i]=i;
int k=0;p=0;
for(int i=1;i<=m*2;i++)
{
int a,b;
a=q[i].x;
b=q[i].y;
if(find(a)!=find(b))
{
add(a,b,q[i].qz);
add(b,a,q[i].qz);
f[find(a)]=find(f[b]);
//cout<<a<<" "<<b<<"\n";
k++;
}
if(k==n-1)
break;
}
dfs(1,1);
c=get_num();
//cout<<ww[5][1]<<" &&&\n";
for(int i=1;i<=c;i++)
{
int qq,w,ans=0;
qq=get_num();w=get_num();
if(find(qq)!=find(w))
{
cout<<-1<<"\n";
continue;
}
ans=just_doit(qq,w);
cout<<ans<<"\n";
}
return 0;
}

噫。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息