51Nod1456 小K的技术

Problem

苏塞克王国是世界上创新技术的领先国家,在王国中有n个城市,标记为1到n。

由于小K的研究,我们最终能过在两个城市之间建立传输管道,一个传输管道能单向连接两个城市,即,一个从城市x到城市y的传输管道不能被用于从城市y传输到城市x。在每个城市之间的运输系统已经建立完善,因此,如果从城市x到城市y的管道和从城市y到城市z的管道都被已经被建立,人们能够立即从x到z。

小K也研究了国家政治,他认为在这m对城市(ai, bi) (1 ≤ i ≤ m)之间的传输尤其重要。他正在计划为每个重要城市对(ai, bi)建立传输管道,通过使用一个或多个传输管道,我们可以从城市ai到城市bi(但不需要从城市bi到城市ai)。我们要找出必须建立的传输管道的最小数。至今,还没有传输管道被建立,在每个城市之间也没有其他有效的传输方式。

Solution

一个弱连通图,如果不包含强连通分量,可以按照拓扑排序连边,则对答案的贡献为n-1,如果包含强连通分量,拓扑以后还有环,对答案的贡献是n,因此先用Tarjan缩点,然后并查集合并弱连通图求个数,再把包含强连通分量的弱连通图个数求出来,答案是点数-(弱连通图个数-含有强连通分量的弱连通图个数)。

Code

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int MAXN=100020;
const int MAXM=100020;
int n,m,idx,cnt,mm;
int g[MAXN],dfn[MAXN],low[MAXN],p2p[MAXN];
bool instack[MAXN];
stack<int>s;
vector<int>belong[MAXN];
struct E{
	int u,v,nex;
	bool operator<(const E x)const{
		if(u==x.u) return v<x.v;
		return u<x.u;
	}
	bool operator==(const E x)const{
		return u==x.u&&v==x.v&&nex==x.nex;
	}
}e[MAXM];
void Tarjan(int u){
	dfn[u]=low[u]=++idx;
	s.push(u);
	instack[u]=true;
	for(int i=g[u];i>0;i=e[i].nex){
		int v=e[i].v;
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(instack[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		++cnt;
		int cur;
		do{
			cur=s.top();s.pop();
			instack[cur]=false;
			belong[cnt].push_back(cur);
			p2p[cur]=cnt;
		}while(cur!=u);
	}
}
int f[100020];
bool ltk[100020];
int ltk_num;
bool havltk[100020];
int havltk_num;
int find(int x){
	return f[x]==0?x:f[x]=find(f[x]);
}
int main(){
	io_opt;
	cin>>n>>m;
	int x,y;
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		e[i]=(E){x,y,g[x]};g[x]=i;
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]) Tarjan(i);	
	}
	
	for(int i=1;i<=m;i++){
		int u=e[i].u,v=e[i].v;
		if(!p2p[u]||!p2p[v]||p2p[u]==p2p[v]){
			e[i].u=e[i].v=1000000;
			e[i].nex=1000000;
		}
		else{
			e[i].u=p2p[u];
			e[i].v=p2p[v];
			e[i].nex=0;
		}
	}
	sort(e+1,e+1+m);
	mm=unique(e+1,e+1+m)-(e+1);
	while(e[mm].nex==1000000) mm--;
	memset(g,0,sizeof(g));
	for(int i=1;i<=mm;i++){
		//cout<<e[i].u<<' '<<e[i].v<<endl;
		e[i].nex=g[e[i].u];
		g[e[i].u]=i;
		int u=find(e[i].u),v=find(e[i].v);
		if(u!=v){
			f[u]=v;
		}
	}
	for(int i=1;i<=cnt;i++){
		int ff=find(i);
		ltk[ff]=true;
		if(belong[i].size()>1){
			havltk[ff]=true;
		}
	}
	for(int i=1;i<=cnt;i++){
		
		if(ltk[i]) ltk_num++;
		if(havltk[i]) havltk_num++;
	}
	//cout<<ltk_num<<endl;
	cout<<n-(ltk_num-havltk_num)<<endl;
	return 0;
}
posted @ 2020-04-03 21:00  CCWUCMCTS  阅读(136)  评论(0编辑  收藏  举报