【BZOJ】1512 [POI2006]Pro-Professor Szu 强联通分量+拓扑

来源:互联网 发布:奔奔数码 淘宝 编辑:程序博客网 时间:2024/06/05 19:13

题目传送门

以后不管打什么代码,一定要过心,不要因为这份代码打过很多遍就放松警惕:这题我因为读优打错了,WA了5发……心塞.jpg

这题的正解是tarjan+拓扑,题目要求n个点到主建筑的方案数,可以考虑主建筑到n个点的方案数,显然答案不变。

对于一个主建筑能到达的、节点数大于1的强连通分量,显然第一问直接输出zawsze。这题还有一个情况,有的点可能有自环,直接当做上面的那个情况考虑即可。

剩下的情况直接在原图中找最长路即可,这个可以用拓扑实现。

p.s.对于第二、三问,主建筑不能走到主建筑……呵呵.png

附上AC代码:

#include <cstdio>#include <cctype>#include <algorithm>#include <queue>using namespace std;const int N=1e6+10,inf=36501;struct side{    int to,nt;}s[N],e[N];int n,m,x,y,num,h[N];int sk[N],d[N],t[N],size,top,sum,sy[N],sz[N];int u[N],rd[N],f[N],put[N],len,ans;queue <int> que;bool b[N],bo[N];inline char nc(){    static char ch[100010],*p1=ch,*p2=ch;    return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;}inline void read(int &a){    static char c=nc();int f=1;    for (;!isdigit(c);c=nc()) if (c=='-') f=-1;    for (a=0;isdigit(c);a=a*10+c-'0',c=nc());    return (void)(a*=f);}inline void so(int x){    d[x]=t[x]=++size,b[x]=1,sk[++top]=x;    for (int i=h[x]; i; i=s[i].nt)        if (!d[s[i].to]) so(s[i].to),t[x]=min(t[x],t[s[i].to]);        else if (b[s[i].to]) t[x]=min(t[x],d[s[i].to]);    if (d[x]==t[x]){        ++sum;        while (1){            int p=sk[top--];b[p]=0,sy[p]=sum;            if (p==x) break;        }    }    return;}int main(void){    read(n),read(m),++n;    for (int i=1; i<=m; ++i){        read(x),read(y),s[++num]=(side){x,h[y]},h[y]=num;        if (x==y) bo[x]=1;    }    for (int i=1; i<=n; ++i) if (!d[i]) so(i);    for (int i=1; i<=n; ++i) ++sz[sy[i]];    num=0;    for (int i=1; i<=n; ++i)        for (int j=h[i]; j; j=s[j].nt)            if (sy[i]!=sy[s[j].to]){                e[++num]=(side){sy[s[j].to],u[sy[i]]},u[sy[i]]=num;                ++rd[sy[s[j].to]];            }    for (int i=1; i<=n; ++i) if (bo[i]) ++sz[sy[i]];    que.push(sy[n]);    if (sz[sy[n]]>1) f[sy[n]]=inf; else f[sy[n]]=1;    while (!que.empty()){        int p=que.front();que.pop();        for (int i=u[p]; i; i=e[i].nt){            f[e[i].to]+=f[p];            if (f[e[i].to]>inf||(sz[e[i].to]>1&&f[e[i].to])) f[e[i].to]=inf;            if ((--rd[e[i].to])==0) que.push(e[i].to);        }    }    for (int i=1; i<n; ++i) ans=max(ans,f[sy[i]]);    printf(ans==inf?"zawsze\n":"%d\n",ans);    for (int i=1; i<n; ++i) if (f[sy[i]]==ans) put[++len]=i;    printf("%d\n",len);    for (int i=1; i<=len; ++i) printf("%d ",put[i]);    return 0;}
原创粉丝点击