BZOJ 1093 ZJOI2007 最大半连通子图 Tarjan+动态规划

来源:互联网 发布:腾讯通rtx2009 mac 编辑:程序博客网 时间:2024/06/15 23:54

题目大意:定义半连通子图为一个诱导子图,其中任意两点(x,y)中x可到达y或y可到达x,求最大半连通子图的大小以及方案数

不就是个缩点之后拓扑序DP求最长链么 这题意逗不逗233333

注意缩点后连边不要连重复了 判重边那里我用了set。。。

#include <set>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 100100using namespace std;int n,m,p;int ans1,ans2;namespace New_Graph{struct abcd{int to,next;}table[1001001];int head[M],tot;int cnt,size[M];int len[M],ways[M];void Add(int x,int y){table[++tot].to=y;table[tot].next=head[x];head[x]=tot;}void Topology_DP(){int i,x;for(x=cnt;x;x--){len[x]=size[x];ways[x]=1;for(i=head[x];i;i=table[i].next){if(len[table[i].to]+size[x]>len[x])len[x]=len[table[i].to]+size[x],ways[x]=0;if(len[table[i].to]+size[x]==len[x])(ways[x]+=ways[table[i].to])%=p;}if(len[x]>ans1)ans1=len[x],ans2=0;if(len[x]==ans1)(ans2+=ways[x])%=p;}}}namespace Old_Graph{struct abcd{int to,next;}table[1001001];int head[M],tot;bool v[M];int belong[M];void Add(int x,int y){table[++tot].to=y;table[tot].next=head[x];head[x]=tot;}void Tarjan(int x){static int dpt[M],low[M],T;static int stack[M],top;int i;low[x]=dpt[x]=++T;stack[++top]=x;for(i=head[x];i;i=table[i].next){if(v[table[i].to])continue;if(dpt[table[i].to])low[x]=min(low[x],dpt[table[i].to]);else{Tarjan(table[i].to);low[x]=min(low[x],low[table[i].to]);}}if(dpt[x]==low[x]){using namespace New_Graph;int t;cnt++;do{t=stack[top--];v[t]=1;belong[t]=cnt;size[cnt]++;}while(t!=x);}}}int main(){using namespace Old_Graph;int i,x,y;cin>>n>>m>>p;for(i=1;i<=m;i++)scanf("%d%d",&x,&y),Add(x,y);for(i=1;i<=n;i++)if(!v[i])Tarjan(i);static set<int> mark[M];for(x=1;x<=n;x++)for(i=head[x];i;i=table[i].next)if(belong[table[i].to]!=belong[x])if(mark[belong[table[i].to]].find(belong[x])==mark[belong[table[i].to]].end()){New_Graph::Add(belong[table[i].to],belong[x]);mark[belong[table[i].to]].insert(belong[x]);}New_Graph::Topology_DP();cout<<ans1<<endl<<ans2<<endl;return 0;}


0 0
原创粉丝点击