結果
| 問題 |
No.1207 グラフX
|
| コンテスト | |
| ユーザー |
ikd
|
| 提出日時 | 2020-09-01 21:41:35 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 446 ms / 2,000 ms |
| コード長 | 8,336 bytes |
| コンパイル時間 | 14,961 ms |
| コンパイル使用メモリ | 402,568 KB |
| 実行使用メモリ | 64,360 KB |
| 最終ジャッジ日時 | 2024-11-20 17:57:12 |
| 合計ジャッジ時間 | 30,591 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 46 |
ソースコード
pub struct ProconReader<R: std::io::Read> {
reader: R,
}
impl<R: std::io::Read> ProconReader<R> {
pub fn new(reader: R) -> Self {
Self { reader }
}
pub fn get<T: std::str::FromStr>(&mut self) -> T {
use std::io::Read;
let buf = self
.reader
.by_ref()
.bytes()
.map(|b| b.unwrap())
.skip_while(|&byte| byte == b' ' || byte == b'\n' || byte == b'\r')
.take_while(|&byte| byte != b' ' && byte != b'\n' && byte != b'\r')
.collect::<Vec<_>>();
std::str::from_utf8(&buf)
.unwrap()
.parse()
.ok()
.expect("Parse Error.")
}
}
#[allow(dead_code)]
mod mint {
use std::ops::{Add, BitAnd, Div, Mul, Rem, Shr, Sub};
#[derive(Copy, Clone)]
pub struct Mint<T> {
x: T,
mo: T,
}
impl<T> Mint<T>
where
T: Copy,
{
pub fn new(x: T, mo: T) -> Mint<T> {
Mint { x, mo }
}
}
impl<T> Mint<T>
where
T: Copy,
{
pub fn val(&self) -> T {
self.x
}
pub fn mo(&self) -> T {
self.mo
}
}
impl<T> Add<T> for Mint<T>
where
T: Copy,
T: Add<Output = T>,
T: Rem<Output = T>,
{
type Output = Mint<T>;
fn add(self, rhs: T) -> Mint<T> {
Mint::new((self.val() + rhs % self.mo()) % self.mo(), self.mo())
}
}
impl<T> Add<Mint<T>> for Mint<T>
where
T: Copy,
Mint<T>: Add<T, Output = Mint<T>>,
{
type Output = Mint<T>;
fn add(self, rhs: Mint<T>) -> Mint<T> {
self + rhs.val()
}
}
impl<T> Sub<T> for Mint<T>
where
T: Copy,
T: Add<Output = T>,
T: Sub<Output = T>,
T: Rem<Output = T>,
{
type Output = Mint<T>;
fn sub(self, rhs: T) -> Mint<T> {
Mint::new(
(self.val() + self.mo() - rhs % self.mo()) % self.mo(),
self.mo(),
)
}
}
impl<T> Sub<Mint<T>> for Mint<T>
where
T: Copy,
Mint<T>: Sub<T, Output = Mint<T>>,
{
type Output = Mint<T>;
fn sub(self, rhs: Mint<T>) -> Mint<T> {
self - rhs.val()
}
}
impl<T> Mul<T> for Mint<T>
where
T: Copy,
T: Mul<Output = T>,
T: Rem<Output = T>,
{
type Output = Mint<T>;
fn mul(self, rhs: T) -> Mint<T> {
Mint::new((self.val() * rhs % self.mo()) % self.mo(), self.mo())
}
}
impl<T> Mul<Mint<T>> for Mint<T>
where
T: Copy,
Mint<T>: Mul<T, Output = Mint<T>>,
{
type Output = Mint<T>;
fn mul(self, rhs: Mint<T>) -> Mint<T> {
self * rhs.val()
}
}
impl<T> Mint<T>
where
T: Copy,
T: Sub<Output = T>,
T: Div<Output = T>,
T: PartialOrd,
T: PartialEq,
T: BitAnd<Output = T>,
T: Shr<Output = T>,
Mint<T>: Mul<Output = Mint<T>>,
{
pub fn pow(self, y: T) -> Mint<T> {
let one = self.mo() / self.mo();
let zero = self.mo() - self.mo();
let mut res = Mint::one(self.mo());
let mut base = self;
let mut exp = y;
while exp > zero {
if (exp & one) == one {
res = res * base;
}
base = base * base;
exp = exp >> one;
}
res
}
}
impl<T> Div<T> for Mint<T>
where
T: Copy,
T: Sub<Output = T>,
T: Div<Output = T>,
T: PartialOrd,
T: PartialEq,
T: BitAnd<Output = T>,
T: Shr<Output = T>,
Mint<T>: Mul<Output = Mint<T>>,
{
type Output = Mint<T>;
fn div(self, rhs: T) -> Mint<T> {
let one = self.mo() / self.mo();
self * Mint::new(rhs, self.mo()).pow(self.mo() - one - one)
}
}
impl<T> Div<Mint<T>> for Mint<T>
where
T: Copy,
Mint<T>: Div<T, Output = Mint<T>>,
{
type Output = Mint<T>;
fn div(self, rhs: Mint<T>) -> Mint<T> {
self / rhs.val()
}
}
impl<T> Mint<T>
where
T: Copy,
T: Div<Output = T>,
Mint<T>: Div<Output = Mint<T>>,
{
pub fn inv(self) -> Mint<T> {
Mint::one(self.mo()) / self
}
}
impl<T> std::fmt::Display for Mint<T>
where
T: Copy + std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.val())
}
}
impl<T> Mint<T>
where
T: Copy,
T: Sub<Output = T>,
{
pub fn zero(mo: T) -> Mint<T> {
Mint { x: mo - mo, mo }
}
}
impl<T> Mint<T>
where
T: Copy,
T: Div<Output = T>,
{
pub fn one(mo: T) -> Mint<T> {
Mint { x: mo / mo, mo }
}
}
}
use mint::Mint;
pub struct UnionFind {
par: Vec<usize>,
size: Vec<usize>,
}
impl UnionFind {
pub fn new(n: usize) -> UnionFind {
UnionFind {
par: (0..n).map(|i| i).collect::<Vec<_>>(),
size: vec![1; n],
}
}
pub fn find(&mut self, i: usize) -> usize {
if self.par[i] == i {
self.par[i]
} else {
self.par[i] = self.find(self.par[i]);
self.par[i]
}
}
pub fn unite(&mut self, i: usize, j: usize) {
let i = self.find(i);
let j = self.find(j);
if i == j {
return;
}
let (i, j) = if self.size[i] >= self.size[j] {
(i, j)
} else {
(j, i)
};
self.par[j] = i;
self.size[i] += self.size[j];
}
pub fn same(&mut self, i: usize, j: usize) -> bool {
self.find(i) == self.find(j)
}
pub fn get_size(&mut self, i: usize) -> usize {
let p = self.find(i);
self.size[p]
}
}
#[derive(Debug, Clone)]
struct Edge {
to: usize,
cost: i64,
}
fn minimum_spanning_tree(g: &Vec<Vec<Edge>>) -> Option<Vec<Vec<Edge>>> {
let n = g.len();
let mut edges = vec![];
for i in 0..n {
for e in &g[i] {
edges.push((e.cost, i, e.to));
}
}
edges.sort();
let mut result = vec![vec![]; n];
let mut uf = UnionFind::new(n);
let mut count = 0;
for e in edges {
let (c, from, to) = e;
if !uf.same(from, to) {
uf.unite(from, to);
count += 1;
result[from].push(Edge { to: to, cost: c });
result[to].push(Edge { to: from, cost: c });
}
}
if count == n - 1 {
Some(result)
} else {
assert!(count < n - 1);
None
}
}
fn dfs(g: &Vec<Vec<Edge>>, i: usize, p: usize, size: &mut Vec<usize>) {
size[i] = 1;
for e in &g[i] {
if e.to != p {
dfs(g, e.to, i, size);
size[i] += size[e.to];
}
}
}
fn main() {
let stdin = std::io::stdin();
let mut rd = ProconReader::new(stdin.lock());
let n: usize = rd.get();
let m: usize = rd.get();
let x: usize = rd.get();
let mut g = vec![vec![]; n];
for _ in 0..m {
let u: usize = rd.get();
let v: usize = rd.get();
let w: i64 = rd.get();
g[u - 1].push(Edge { to: v - 1, cost: w });
g[v - 1].push(Edge { to: u - 1, cost: w });
}
let h = minimum_spanning_tree(&g).unwrap();
let mut size = vec![0; n];
dfs(&h, 0, !0, &mut size);
let mut q = std::collections::VecDeque::new();
q.push_back((0, !0, 0, 0));
let mo = 1_000_000_000 + 7;
let mut ans = Mint::zero(mo);
while let Some((i, p, c, acc)) = q.pop_front() {
if p != !0 {
ans = ans + Mint::new(size[i] * acc, mo) * Mint::new(x, mo).pow(c);
}
let mut a = acc + 1;
for e in &h[i] {
if e.to != p {
a += size[e.to];
}
}
for e in &h[i] {
if e.to != p {
q.push_back((e.to, i, e.cost as usize, a - size[e.to]));
}
}
}
println!("{}", ans);
}
ikd