BZOJ 1093: [ZJOI2007]最大半连通子图|tarjan|动态规划

来源:互联网 发布:网络摄像头协议 编辑:程序博客网 时间:2024/06/07 03:19

题意中两个半子图不同是指有点不同

好奇怪的一句话啊

就是子图中包含的点不同,不管边怎样

然后就是tarjan dp

注意不要连重边

窝用的是map判重

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<set>#include<map>#include<vector>#include<algorithm>#include<iostream>#define T 100100using namespace std;int sc(){int i=0; char c=getchar();while(c>'9'||c<'0') c=getchar();while(c>='0'&&c<='9') i=i*10+c-'0',c=getchar();return i;}int Head[T],Nxt[T*10],Lst[T*10],mx[T],sum[T];int dfn[T],low[T],size[T],bl[T],st[T],vis[T];int head[T],nxt[10*T],lst[10*T];int Tot,tot,n,m,K,top,cnt,scc;map<pair<int,int>,int>mp;void Insert(int x,int y){Lst[++Tot]=y;Nxt[Tot]=Head[x];Head[x]=Tot;}void insert(int x,int y){lst[++tot]=y;nxt[tot]=head[x];head[x]=tot;}void tarjan(int x){low[x]=dfn[x]=++cnt;st[++top]=x;vis[x]=1;for(int i=head[x];i;i=nxt[i]){if(vis[lst[i]])low[x]=min(low[x],dfn[lst[i]]);else if(!dfn[lst[i]]){tarjan(lst[i]);low[x]=min(low[x],low[lst[i]]);}}if(dfn[x]==low[x]){int k=0;scc++;while(k!=x){k=st[top--];bl[k]=scc;size[scc]++;vis[k]=0;}}}void dfs(int x){vis[x]=1;for(int i=Head[x];i;i=Nxt[i]){if(!vis[Lst[i]]) dfs(Lst[i]);if(mx[x]<mx[Lst[i]]){mx[x]=mx[Lst[i]];sum[x]=sum[Lst[i]];}else if(mx[x]==mx[Lst[i]])    sum[x]=(sum[x]+sum[Lst[i]])%K;}if(mx[x]==0)sum[x]=1;mx[x]+=size[x];//cout << x <<" "<<mx[x]<<" "<<sum[x]<<endl;}int main(){n=sc(),m=sc(),K=sc();for(int i=1;i<=m;i++){int x=sc(),y=sc();insert(x,y);}for(int i=1;i<=n;i++)    if(!dfn[i])tarjan(i);for(int i=1;i<=n;i++)    for(int j=head[i];j;j=nxt[j])        if(bl[i]!=bl[lst[j]])        {        if(!mp[make_pair(bl[i],bl[lst[j]])])                Insert(bl[i],bl[lst[j]]),                mp[make_pair(bl[i],bl[lst[j]])]=1;        }int MX=0,ans=0;for(int i=1;i<=scc;i++){    if(!vis[i]) dfs(i);    if(mx[i]>MX)    {    MX=mx[i];    ans=sum[i];    }    else if(mx[i]==MX)        ans=(ans+sum[i])%K;}cout<<MX<<endl<<ans;return 0;}


0 0