zoukankan      html  css  js  c++  java
  • [ZJOI2007]最大半连通子图

    tarjan缩点+拓扑排序+DP。
    让求的其实是缩点后最长链的长度和最长链的个数。基本操作。(注意去重边。。。)

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    queue<int>q;
    const int N=100005,M=1000005;
    vector<int>G[N];
    int n,m,mod,head[N],ecnt,dfn[N],low[N],tim,stk[N],top,cnt,col[N],sum[N],num[N],ru[N],mxlen[N],f[N],ans;
    long long counts;
    bool instk[N];
    struct Edge{int to,nxt;}e[M];
    void add(int bg,int ed){e[++ecnt].to=ed;e[ecnt].nxt=head[bg];head[bg]=ecnt;}
    void topsort() {
    	for(int i=1;i<=cnt;i++) if(!ru[i])q.push(i),mxlen[i]=sum[i],f[i]=1;
    	while(!q.empty()) {
    		int u=q.front();q.pop();ans=max(ans,mxlen[u]);
    		for(int i=0;i<G[u].size();i++) {
    			int v=G[u][i];ru[v]--;
    			if(ru[v]==0) q.push(v);
    			if(mxlen[v]<sum[v]+mxlen[u]) mxlen[v]=sum[v]+mxlen[u],f[v]=f[u];
    			else if(mxlen[v]==mxlen[u]+sum[v]) (f[v]+=f[u])%=mod;
    		}
    	}
    }
    void tarjan(int x){
    	low[x]=dfn[x]=++tim;stk[++top]=x;instk[x]=1;
    	for(int i=head[x];i;i=e[i].nxt) {
    		int v=e[i].to;
    		if(!dfn[v]) {tarjan(v);low[x]=min(low[x],low[v]);}
    		else if(instk[v]) low[x]=min(low[x],dfn[v]);
    	}
    	if(dfn[x]==low[x]) {
    		int k;cnt++;
    		do{
    			k=stk[top--];
    			col[k]=cnt;
    			sum[cnt]++;
    			instk[k]=0;
    		}while(k!=x);
    	}
    }
    struct AA{int x,y;}d[M];
    bool cmp(AA x,AA y){
    	return x.x==y.x?x.y<y.y:x.x<y.x;
    }
    int main() {
    	scanf("%d%d%d",&n,&m,&mod);
    	for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),add(u,v),d[i].x=u,d[i].y=v;
    	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    	for(int i=1;i<=m;i++) d[i].x=col[d[i].x],d[i].y=col[d[i].y];
    	sort(d+1,d+1+m,cmp);
    	for(int i=1,lastx=0,lasty=0;i<=m;i++) {
    		if(d[i].x!=d[i].y&&(d[i].x!=lastx||d[i].y!=lasty)) G[d[i].x].push_back(d[i].y),ru[d[i].y]++;
    		lastx=d[i].x,lasty=d[i].y;
    	}
    	topsort();
    	for(int i=1;i<=cnt;i++)if(mxlen[i]==ans) counts=(counts+f[i])%mod;
    	cout<<ans<<"
    "<<counts;
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    P2009 跑步
    P3916 图的遍历
    P2865 [USACO06NOV]路障Roadblocks
    P2820 局域网
    P2176 [USACO14FEB]路障Roadblock
    讨伐!数论
    网络流入门——EK算法
    最被低估的特质
    我的天哪我有博客了!
    Area POJ
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9378760.html
Copyright © 2011-2022 走看看