nowcoder多校6G(最小割理解+dfs)

这个题出得比较新颖的。。简单地考验对最小割的分析。。感觉今年区域赛也可能会出这种。。

首先在完全图上跑最大流其实也即跑最小割。。。然后将s和t放在两旁可以发现割中间点之间的边显然是没什么太大帮助的。。所以只能割连s的所有边或者连t的所有边。。然后可能会有个顾虑就是中间点之间的边会远远小于割去的边,其实边权是由距离形成的所以边权差并不会太大。。

然后问题就变成了求每个点到所有点的距离和。。这个优秀的汪聚聚告诉我们可以2遍dfs跑过去。。要积累下来。。

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 100005
#define nm 200005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const ll inf=1e9+7;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}


struct edge{int t;ll v;edge*next;}e[nm],*h[NM],*o=e;
void add(int x,int y,int v){o->v=v;o->t=y;o->next=h[x];h[x]=o++;}
int n,_x,_y,_t,size[NM],f[NM],ca,b[50],tot;
__int128 cnt[NM],d[NM],ans;

void dfs1(int x){
    size[x]=1;d[x]=0;
    link(x)if(f[x]!=j->t){
	f[j->t]=x;dfs1(j->t);
	d[x]+=d[j->t]+j->v*size[j->t];
	size[x]+=size[j->t];
    }
}

void dfs2(int x){
    link(x)if(f[x]!=j->t){
	cnt[j->t]=cnt[x]+j->v*(n-2*size[j->t]);
	dfs2(j->t);
    }
}


int main(){
    int _=read();while(_--){
	ans=0;mem(e);mem(h);o=e;tot=0;
	n=read();
	inc(i,1,n-1){_x=read();_y=read();_t=read();add(_x,_y,_t);add(_y,_x,_t);}
	dfs1(1);cnt[1]=d[1];dfs2(1);
	//inc(i,1,n)printf("%d ",cnt[i]);putchar('\n');
	sort(cnt+1,cnt+1+n);
	inc(i,1,n)ans+=cnt[i]*(n-i);
	printf("Case #%d: ",++ca);
	while(ans)b[++tot]=ans%10,ans/=10;
	dec(i,tot,1)printf("%d",b[i]);putchar('\n');
    }
    return 0;
}

链接:https://www.nowcoder.com/acm/contest/144/G
来源:牛客网
 

Pikachu

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

In Viridian forest there is a tree T formed by N nodes, each edge on which has a positive weight.

There is an undirected graph G generated from tree T, which contains N nodes and undirected edges, where the capacity of the edge between u and v equals to the distance between them on the tree T.

Given the tree T, Pikachu wants to calculate the sum of the max flow between every two nodes in G, there are different pairs of nodes should be counted. Could you help him?

输入描述:

The input starts with one line containing exactly one integer t, which is the number of test cases.

For each test case, the first line contains one integer N, indicating the size of the tree T.

Then followed by N - 1 lines, each consists of three integers ui, vi and wi, representing the two nodes connected by the i-th edge and the weight of the i-th edge.

- 1 ≤ t ≤ 10.
- 2 ≤ N ≤ 105.
- 1 ≤ wi ≤ 1000.
- 

输出描述:

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the sum of the maximum flow between every two nodes in G.

示例1

输入

复制

2
3
1 2 1
2 3 1
5
1 2 1
2 3 1
2 4 1
4 5 2

输出

复制

Case #1: 7
Case #2: 72

猜你喜欢

转载自blog.csdn.net/qkoqhh/article/details/81569228
6g