其他分享
首页 > 其他分享> > FOJ 滑水路线

FOJ 滑水路线

作者:互联网

题目描述

在一条笔直的河流中,有N个站点排成一条直线,从左往右编号为1~N(1<=N<=1000),并有M条滑水路线(1<=M<=10000),路线连接某两个站点(从某个站点连向另一站点地有向边,可能存在自环,也就是同一个站点作为起点终点),保证所有在划水线路中的站点直接或间接地相连。

FLY从1号站点出发,他希望把所有滑水路线不重复地划上一遍,最后回到1号站点。

如果FLY只是走滑水路线,那么这个愿望很可能无法完成,因为无法保证某些路线只重复走一次。

所以FLY除了走滑水线路还可以选择直接走路到其他站点。

但是FLY并不想走太多路,你能帮他计算一下最少走路的长度吗?(从1号站点出发,不重复经过每条划水线路一次,回到1号站点)

输入

 第1行:两个整数 N 和 M ,用空格隔开.
 第2到 N+1 行:第 i+1 行包括一个整数 Xi,表示 i 号站点距河左侧源头的距离.
 第 N+2 到 M+N+1 行:第 i+N+1 行包括两个整数 S和 D,分别表示了一条滑水路线的起点和终点.

输出

输出一个整数,即FLY要走的路程长度至少为多少米

分析

因为要刚好经过每条边一次,所以我们可以考虑一个点的入度与出度之差

如果刚好为 0 ,显然不用走路

如果不为 0,一定是从最近的也不为 0 的点转移过来最优

这里可以借鉴一下 均分纸牌 的思想,可见 P1031 [NOIP2002 提高组] 均分纸牌 - jiangchenyangsong 的博客 - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define N 10005
#define int long long
using namespace std;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
int n,m;
struct obj{
    int x,d;
}a[N];
bool cmp(obj x,obj y){
    return x.x<y.x; 
}
signed main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i].x=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        a[x].d++,a[y].d--;
    }
    sort(a+1,a+1+n,cmp);
    int ans=0;
    for(int i=1;i<n;i++){
        ans+=abs(a[i].d)*(a[i+1].x-a[i].x);
        a[i+1].d+=a[i].d;
    }
    printf("%lld\n",ans);
    return 0;
} 

 

标签:FLY,站点,ch,滑水,int,路线,FOJ
来源: https://www.cnblogs.com/jiangchenyyds/p/16534697.html