题目翻译
这次不放原题题面了。
题目叙述
炎热的夏日里,约翰带贝茜去水上乐园滑水.滑水是在一条笔直的人工河里进行的,沿河设有 N N N ( 1 ≤ N ≤ 10000 1≤N≤10000 1≤N≤10000 )个中转站,并开通了 M M M ( 1 ≤ M ≤ 10000 1≤M≤10000 1≤M≤10000 )条滑水路线。路线的起点和终点总在某个中转站上,起点和终点可能相同.有些中转站可能是许多条路线的起点或终点,而有些站则可能没有在任何路线里被用上。贝茜希望能把所有的路线都滑一遍。 所有中转站排成一条直线,每个中转站位于离河的源头 X i X_i Xi ( 0 ≤ X i ≤ 100000 (0≤X_i≤100000 (0≤Xi≤100000 )米处.沿着河边的人行道,贝茜可以从任意位置走到任意一个中转站。 中转站与滑水路线的布局满足下述的性质:任意两个中转站之间都有滑水路线直接成间接相连。水上乐园的入口与出口都在1号中转站旁,也就是说,贝茜的滑水路线的起点和终点都是1号中转站。
为了更好地享受滑水的快乐,贝茜希望自己花在走路上的时间越少越好.请你帮她计算一下,如果按她的计划,把所有的路线都不重复地滑一遍,那她至少要走多少路。
输入
- 第 1 1 1 行:两个整数 N N N 和 M M M ,用空格隔开。
- 第2到 N + 1 N+1 N+1 行:第 i + 1 i+1 i+1 行包括一个整数 X i Xi Xi ,表示i号中转站距河源头的距离。
- 第N+2到M+N+1行:第i+N+1行包括两个整数Si和Di,分别表示了一条滑水路线的起点和终点。
输出
输出一个整数,即贝茜要走的路程长度至少为多少米。
输入样例
5 7
5
3
1
7
10
1 2
1 2
2 3
3 1
4 5
1 5
4 1
输出样例
8
提示
贝茜先按1~2~3~1~2路径滑水.然后走2米,回到1.她再滑行到5,走到4,滑行
到5,走到4,最后滑回1(数字代表中转站号)。
这样,她所走的总路程为 8 8 8 米。
题目解析
解法一:建图然后跑一次网络流,无疑 T 飞。
然后我们发现,如果一个中转站的出度和入度是相等的,那么肯定就不会从这个中转站出发或者走到中转站,如果这个中转站的出度减去入度为 1 1 1 ,那么肯定是从一个地方走到这个中转站。
也就是说,我们只要知道每个中转站的出度和入度就可以得出这个车站的进出。
然后考虑如何得到正确答案,我们先看一道题目:Link
我们就可以使用类似于解这道题目的思路,把每个节点的出度减入度的值“移”到这个点右边的点上,代价就是 度的值 × \times ×距离。答案就是所有的代价之和,不难证明到了最后,入度减去出度的值就是 0 0 0。
当然,为了保证我们是按中转站从左至右的处理顺序,我们要把每个中转站的距离和出度减去入度的值放在结构体里面排序。
代码:
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2039
#define js(x) ((x)*(x))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
typedef int Type;
inline Type read(void){
Type sum=0;
int flag=0;
char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
if(flag) return -sum;
return sum;
}
struct JTZ{
int dist,x,y;
bool operator < (const JTZ x) const{
return this->dist< x.dist;
}
};
JTZ dist[maxn*maxn];
int x[maxn],y[maxn];
int pd[maxn],ans[maxn],pa[maxn];
int n,m,maxx;
int d,a,b,cnt;
int main(){
n=read();
register int i,j;
for(i=1;i<=n;i++){
x[i]=read();
y[i]=read();
}
cnt=0;
for(i=0;i<n;i++)
for(j=i+1;j<=n;j++)
dist[++cnt]=(JTZ){
js(x[i]-x[j])+js(y[i]-y[j]),i,j};
sort(dist+1,dist+cnt+1);
for(i=1;i<=cnt;i++){
d=dist[i].dist;
a=dist[i].x;
b=dist[i].y;
if(d!=pd[a]){
pd[a]=d;
pa[a]=ans[a];
}
if(d!=pd[b]){
pd[b]=d;
pa[b]=ans[b];
}
if(a==0){
ans[a]=max(ans[a],pa[b]);
}
else{
ans[a]=max(ans[a],pa[b]+1);
ans[b]=max(ans[b],pa[a]+1);
}
}
printf("%d",ans[0]+1);
return 0;
}