Tarjan-bzoj1093: [ZJOI2007]最大半连通子图

来源:互联网 发布:dnf老是出现数据异常 编辑:程序博客网 时间:2024/05/24 01:51

http://www.lydsy.com/JudgeOnline/problem.php?id=1093
先太监缩点,之后就变成了拓扑图;
第一问就是问最长链嘛,这个大家基本上全在用拓扑排序去搞;
其实dfs就好了……………………..
然后,求数量,这个直接在dfs里面乱搞就好了;
然后这个取模,如果你dp的话没问题;
反正dfs的时候要比较大小的;
这个时候就用高精度就好了;
就是再开一个数组存x取了几次莫;
然后比较就乱搞;
但是会重边;
其实我们只要dfs到一个点x时;
我们去搜索其子节点的时候不去重复;
那么直接再搞一个数组就好了;

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cmath>#include<cstring>#define Ll long longusing namespace std;struct cs{    Ll to,next;}a[1000001];//f[i]是i点的最优结果;ff[i]是结果的次数%X;fff[i]是结果取了几次%; Ll head[100001],tt[100001],lin[100001],low[100001],c[1000001][2],q[100001],f[100001],ff[100001],fff[100001],sum[100001];bool in[100001];Ll x,y,z,n,m,ans,ll,Ans,ANS,t,X,nn;void init(Ll x,Ll y){    a[++ll].to=y;    a[ll].next=head[x];    head[x]=ll;}void dfs(Ll x){    low[x]=tt[x]=++t; in[x]=1; q[++q[0]]=x;    for(int k=head[x];k;k=a[k].next){        if(!tt[a[k].to])dfs(a[k].to);        if(in[a[k].to])low[x]=min(low[x],low[a[k].to]);    }    if(low[x]==tt[x]){        nn++;        while(1){            lin[q[q[0]]]=nn;            in[q[q[0]]]=0;            sum[nn]++;            q[0]--;            if(q[q[0]+1]==x)break;        }    }}void find(Ll x){    in[x]=1; t++;//这个tt代表循环次数     for(int k=head[x];k;k=a[k].next){        if(!in[a[k].to])find(a[k].to);        //其实我的程序有鬼的,但是不知为什么AC了        //我的t在同一层会变的啊!!!!!;         if(tt[a[k].to]==t)continue;else tt[a[k].to]=t;//这个就是去重边,t++就免去了memset;         if(f[a[k].to]==f[x]){             ff[x]+= ff[a[k].to];            fff[x]+=fff[a[k].to];//类似高精度             fff[x]+=ff[x]/X;            ff[x]%=X;               }        if(f[a[k].to]>f[x])f[x]=f[a[k].to],ff[x]=ff[a[k].to],fff[x]=fff[a[k].to];    }    if(f[x])f[x]+=sum[x];else f[x]=sum[x],ff[x]=1,fff[x]=0;    if(f[x]==ans){        Ans+=ff[x];        ANS+=fff[x];        ANS+=Ans/X;        Ans%=X;    }    if(f[x]>ans)ans=f[x],Ans=ff[x],ANS=fff[x];}int main(){    scanf("%lld%lld%lld",&n,&m,&X);    for(int i=1;i<=m;i++){        scanf("%lld%lld",&c[i][0],&c[i][1]);        init(c[i][0],c[i][1]);    }    for(int i=1;i<=n;i++)if(!tt[i])dfs(i);//tarjan     memset(head,0,sizeof head);ll=0;    for(int i=1;i<=m;i++){        x=lin[c[i][0]];y=lin[c[i][1]];        if(x==y)continue;        init(x,y);    }    memset(in,0,sizeof in);    memset(tt,0,sizeof tt);t=0;    for(int i=1;i<=nn;i++)if(!in[i])find(i);    printf("%lld\n%lld",ans,Ans);}

其实这个程序问题很大;
首先根本不用fff数组呵呵呵;
呵呵呵呵呵呵………………..
ANS答案根本无关系
然后那个t还有漏洞(数据水)
其实那个t要另开变量存起来……..
但是思路是对的
那就不改了.
呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵
感谢jzqjzq指出我的错误;本垃圾;还需大家指点;

0 1
原创粉丝点击