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 行包括两个整数 Si 和 Di ,分别表示了一条滑水路线的起点和终点.
输出
输出一个整数,即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