题目描述
![]()
输入
![]()
输出
![]()
样例输入
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; }
[BZOJ3390]荒岛野人
最新推荐文章于 2022-11-10 00:53:56 发布