敌敌

【问题描述】

月考刚考了年级倒数的敌敌来到电脑室,朝着正在写树套树套树套树的beginend大吼:我就不信我有辣么辣鸡!我可是去年普及组AC了第一题的人啊!
beginend不耐烦地扔了一道题给敌敌,然后说:你只要把这道题写出来你就不是辣鸡啦。
敌敌接过题一看,题目是这样的:
有n个点和n-1条无向边,满足任意两点都可以互相到达,求有多少条经过且仅经过三个点的简单路径。
(简单路径即为每个点最多被访问一次的路径)
但是敌敌发现自己并不会写这题,但又不愿承认自己是辣鸡这个事实,于是他就拿着题目来找刚刚成为保送狗的你。为了敌敌的智商,你只好选择了帮他一把。

【输入格式】
第一行一个正整数n表示城市数量。
接下来n-1行每行两个正整数u,v表示u和v之间有一条道路。

【输出格式】

输出一行,表示经过且仅经过三个点的简单路径的数量。

【题解】
暴力!

【代码】

var
  ans:int64;
  n:longint;
  f,sum:array [0..200001] of longint;
  a:array [0..400001,1..2] of longint;
procedure init;
var
  i,x,y:longint;
begin
  readln(n);
  for i:=1 to n-1 do
    begin
      readln(x,y);
      a[i,1]:=x; a[i,2]:=y;
      a[n+i-1,1]:=y; a[n+i-1,2]:=x;
      inc(f[x]); inc(f[y]);
    end;
  ans:=0;
end;

procedure qsort(l,r:longint);
var
  i,j,mid,t:longint;
begin
  if l>r then exit;
  i:=l; j:=r;
  mid:=a[(l+r) div 2,1];
  repeat
    while a[i,1]<mid do inc(i);
    while a[j,1]>mid do dec(j);
    if i<=j then
      begin
        t:=a[i,1]; a[i,1]:=a[j,1]; a[j,1]:=t;
        t:=a[i,2]; a[i,2]:=a[j,2]; a[j,2]:=t;
        inc(i); dec(j);
      end;
  until i>j;
  qsort(i,r);
  qsort(l,j);
end;

procedure main;
var
  i,j:longint;
begin
  fillchar(sum,sizeof(sum),0);
  sum[1]:=1;
  for i:=2 to n do
    sum[i]:=f[i-1]+sum[i-1];
  sum[n+1]:=sum[n]+1;
  for i:=1 to n do
    for j:=sum[i] to sum[i+1]-1 do
      ans:=ans+f[a[j,2]]-1;
  write(ans);
end;

begin
  assign(input,'didi.in');
  assign(output,'didi.out');
  reset(input);
  rewrite(output);
  init;
  qsort(1,n*2-2);
  main;
  close(input);
  close(output);
end.
原文地址:https://www.cnblogs.com/zyx-crying/p/9319551.html