[BZOJ3390]荒岛野人

题目描述


输入



输出



样例输入

8 7
3 4
1 2
2 3
3 1
3 6
4 5
7 8
1 1
0 0
0 0
0 1
1 0
1 0
1 0

0 1


样例输出
3
0
0
0
2
2

1


数据规模


来源 by azui



题解:找桥(又称割边)。

若一条边不是桥,则答案为0;

若边是桥,算出其连接的两个联通快A,B中男女总人数Am,Aw,Bm,Bw,答案为Am*Bw+Aw*Bm。


#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int N=1e5+10;
const int M=1e6+10;


int n, m, fir[N], ecnt=1;
struct node{ int e, next, t; } edge[M];
void Link( int s, int e ) {
	edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt;
	edge[++ecnt].e=s; edge[ecnt].next=fir[e]; fir[e]=ecnt;
}


struct nodes{ LL m, w; }land[N], area[N];
int dfn[N], low[N], dfs_clock, sumt;
void DFS( int r, int fa ) {
	dfn[r]=low[r]=++dfs_clock;
	for( int i=fir[r]; i; i=edge[i].next )
		if( !dfn[ edge[i].e ] ) {
			DFS( edge[i].e, r );
			low[r]=min( low[r], low[ edge[i].e ] );
			if( low[ edge[i].e ]>dfn[r] ) edge[i].t=edge[i^1].t=sumt;
			
			land[r].m+=land[ edge[i].e ].m;
			land[r].w+=land[ edge[i].e ].w;
		}
		else if( edge[i].e!=fa )
			low[r]=min( low[r], dfn[ edge[i].e ] );
}


int s, e;
int main() {
	scanf( "%d%d", &n, &m );
	for( int i=1; i<=m; i++ ) {
		scanf( "%d%d", &s, &e );
		Link( s, e );
	}
	for( int i=1; i<=n; i++ )
		scanf( "%lld%lld", &land[i].m, &land[i].w );
	
	for( int i=1; i<=n; i++ )
		if( !dfn[i] ) {
			sumt++; DFS( i, -1 );
			area[sumt].m=land[i].m;
			area[sumt].w=land[i].w;
		}
	
	for( int i=2; i<=ecnt; i+=2 )
		if( edge[i].t ) {
			LL m1=min( land[ edge[i].e ].m, land[ edge[i^1].e ].m );
			LL w1=min( land[ edge[i].e ].w, land[ edge[i^1].e ].w );
			LL m2=area[ edge[i].t ].m-m1;
			LL w2=area[ edge[i].t ].w-w1;
			printf( "%lld\n", m1*w2+m2*w1 );
		}
		else printf( "0\n" );
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值