Mathematical Tarjan seeking cutpoint + [POI2008] BLO-Blockade (Los Valley P3469)

[POI2008]BLO-Blockade

Title Description

There are exactly nn towns in Byteotia.

Some towns are connected by bidirectional roads.

There are no crossroads outside towns, though there may be bridges, tunnels and flyovers. Each pair of towns may be connected by at most one direct road. One can get from any town to any other-directly or indirectly.

Each town has exactly one citizen.

For that reason the citizens suffer from loneliness.

It turns out that each citizen would like to pay a visit to every other citizen (in his host’s hometown), and do it exactly once. So exactly n\cdot (n-1)n⋅(n−1) visits should take place.

That’s right, should.

Unfortunately, a general strike of programmers, who demand an emergency purchase of software, is under way.

As an act of protest, the programmers plan to block one town of Byteotia, preventing entering it, leaving it, and even passing through.

As we speak, they are debating which town to choose so that the consequences are most severe.

Task Write a programme that:

reads the Byteotian road system’s description from the standard input, for each town determines, how many visits could take place if this town were not blocked by programmers, writes out the outcome to the standard output.

Given an undirected graph, each point after the request has been blocked ordered number of points (x, y) (x! = Y, 1 <= x, y <= n) of x and y can not be reached

Input Format

In the first line of the standard input there are two positive integers: nn and mm (1\le n\le 100\ 0001≤n≤100 000, 1\le m\le 500\ 0001≤m≤500 000) denoting the number of towns and roads, respectively.

The towns are numbered from 1 to nn.

The following mm lines contain descriptions of the roads.

Each line contains two integers aa and bb (1\le a<b\le n1≤a<b≤n) and denotes a direct road between towns numbered aa and bb.

The first row is read n, m, are the number of towns and the number of road

Output Format

Your programme should write out exactly nn integers to the standard output, one number per line. The i^{th}i
th
line should contain the number of visits that could not take place if the programmers blocked the town no. ii.
城镇编号1~n

The next two lines each m numbers a, b, has expressed an undirected edge between a and b

N output lines, each digit line, the number of accesses can not occur when the i-th lock towns.


Tarjan cut points obtained while obtaining the equivalent of a cutting edge, this edge is the number of sub-tree to be recorded at the back to be calculated;

When the point is determined for each cut point, the cutting edge also determined for each cut point there are several connections, each size is the number of subtrees;

Then you can use a little math to calculate the size;

Difficulty: is more difficult to think of statistics for each connection point cut cutting edge of the sub-tree size, a mathematical formula is better push;

Code:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=100010;
const int M=1000100;
const LL mod=100000000;
int dfn[N],low[N],tot,head[N],cnt,n,m,vis[N];
vector<LL>ve[N];
struct Node{
	int to,nex;
}edge[M];
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].nex=head[p];
	head[p]=cnt++;
}
int Tarjan(int p,int fa){
	dfn[p]=low[p]=++tot;
	int ch=0;//儿子数量 
	int sum1=1,sum2=1;
	for(int i=head[p];~i;i=edge[i].nex){
		int q=edge[i].to;
		if(!dfn[q]){
			ch++;
			int s=Tarjan(q,p);
			sum1+=s;
			low[p]=min(low[p],low[q]);
			if(p!=fa&&low[q]>=dfn[p]){
				sum2+=s;
				ve[p].push_back(1ll*s);
				vis[p]=1;
			}
			if(p==fa&&ch>=2){
				sum2+=s;
				ve[p].push_back(1ll*s);
				vis[p]=1;
			}
		}
		else if(q!=fa) low[p]=min(low[p],dfn[q]);
	}
	ve[p].push_back(1ll*(n-sum2));
	return sum1;
}
int main(){
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y),add(y,x);
	}
	Tarjan(1,1);
	for(int i=1;i<=n;i++){
		if(vis[i]){
			LL ans=0;
			for(int j=0;j<ve[i].size();j++){
				ans+=(1ll*n-ve[i][j])*ve[i][j];
			}
			ans+=1ll*(n-1);
			printf("%lld\n",ans);
		}
		else printf("%lld\n",2ll*(n-1));
	}
    return 0;
}

Published 264 original articles · won praise 46 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_44291254/article/details/104999950