社区讨论

本地能过,一交全部re(大悲

P2272[ZJOI2007] 最大半连通子图参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@loobd3b0
此快照首次捕获于
2023/11/07 20:34
2 年前
此快照最后确认于
2023/11/07 20:44
2 年前
查看原帖
CPP
#include <bits/stdc++.h>
using namespace std;

const int N=1e5+1145,M=1e6+11451;
typedef long long ll;
int n,m,mo,in[N];
ll ans,fans,f[N],g[N];

int first[N],idx,first1[N],idx1;
struct edge{
	int d,ne;
}ed[M*2],ed1[M*2];

void add_edge(int e,int d){
	idx++;
	ed[idx].d=d;
	ed[idx].ne=first[e];
	first[e]=idx;
}
void add_edge1(int e,int d){
	idx1++;
	ed1[idx1].d=d;
	ed1[idx1].ne=first1[e];
	first1[e]=idx1;
}
int all;
struct node{
	int e,d;
}eg[M*2];
bool cmp(node l,node r){
	if(l.e==r.e) return l.d<r.d;
	return l.e<r.e;
}

int sz[N],dfn[N],low[N],tot,cnt,stk[N],top,bel[N];
bool vis[N];
void tarjan(int now){
	dfn[now]=low[now]=++tot;
	stk[++top]=now;
	vis[now]=true;
	for(int i=first[now];i;i=ed[i].ne){
		int d=ed[i].d;
		if(!dfn[d]){
			tarjan(d);
			low[now]=min(low[now],low[d]);
		}else if(vis[d]) low[now]=min(low[now],dfn[d]);
	}
	if(low[now]==dfn[now]){
		int y;
		cnt++;
		do{
			y=stk[top--];
			bel[y]=cnt;
			sz[cnt]++;
			vis[y]=false;
		}while(y!=now);
	}
}
queue<int> q;
int main()
{
	cin>>n>>m>>mo;
	for(int i=1;i<=m;i++){
		int e,d;
		scanf("%d%d",&e,&d);
		add_edge(e,d);
	}
	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
	
	for(int i=1;i<=n;i++){
		for(int j=first[i];j;j=ed[i].ne){
			int d=ed[j].d;
			if(bel[d]==bel[i]) continue;
			eg[++all]={bel[i],bel[d]};
		}
	}
	sort(eg+1,eg+1+all,cmp);
	for(int i=1;i<=all;i++){
		if(eg[i].e==eg[i-1].e&&eg[i].d==eg[i-1].d) continue;
		add_edge1(eg[i].e,eg[i].d);
		in[eg[i].d]++;
		//cout<<eg[i].e<<" "<<eg[i].d<<endl;
	}
	for(int i=1;i<=cnt;i++) if(!in[i]) {
		q.push(i);
		f[i]=sz[i];
		g[i]=1;
	}
	while(!q.empty()){
		int t=q.front();
		q.pop();
		ans=max(ans,f[t]);
		for(int i=first1[t];i;i=ed1[i].ne){
			int d=ed1[i].d;
			if(f[t]+sz[d]>f[d]){
				f[d]=f[t]+sz[d];
				g[d]=g[t];
			}else if(f[t]+sz[d]==f[d]) g[d]=(g[d]+g[t])%mo;
			in[d]--;
			if(!in[d]) q.push(d);
		}
	}
	cout<<ans<<endl;
	for(int i=1;i<=cnt;i++) {
		if(f[i]==ans)
			fans=(fans+g[i])%mo;
	}
	
	cout<<fans;
	puts("");
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...