• bzoj1064: [Noi2008]假面舞会


    莫名其妙的dfs算法。

    1.这道题首先要推出来,如果有弓形或者环形,答案必须是环长度和弓形俩条路长度之差的约数。

    而且如果你直接按照原图来建图你是跑不出来的。

    1.如果你每个点访问一次时dfs所有点,tle。

    2.如果你打vis标记,你判断不出来弓形,wa。

    3.如果妄图用一个in数组记录哪个点in[u]=0,然后从这个点开始跑的话。整体做个环,甩出去个头支的。wa+奇奇怪怪的错误。

    所以我们要求每个点逆向也可以跑。

    所以建图为 a->b 1,b->a->-1。

    这样上述问题就不会出现了。

    2.如果没有上述情况,肯定就是个dag图。跑dfs就行了。

    然后求最多可能有多少类面具的答案为sum(最长链的长度)。用心去感受

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    const int maxn = 100000 + 10;
    const int maxm = 4000000 + 10;
    const int inf = 0x3f3f3f3f;
    int g[maxn],v[maxm],next[maxm],dist[maxm],eid;
    int c[maxn];
    bool vis[maxn],inque[maxn],mark;
    int n,m,ans,l,r,minres,maxres,u;
    queue<int> q;
    
    void addedge(int a,int b,int c) {
        v[eid]=b; dist[eid]=c; next[eid]=g[a]; g[a]=eid++;    
    }
    
    int gcd(int a,int b) {
        return b==0?a:gcd(b,a%b);    
    }
    
    void dfs(int u,int fa,int d) {
        if(vis[u]) {
            ans=gcd(ans,abs(d-c[u]));
            return;
        }
        vis[u]=1;
        c[u]=d;
        for(int i=g[u];~i;i=next[i]) if(v[i]!=fa) dfs(v[i],u,c[u]+dist[i]);
    }
    
    void build() {
        memset(g,-1,sizeof(g));
        scanf("%d%d",&n,&m);
        for(int i=1,a,b;i<=m;i++) {
            scanf("%d%d",&a,&b);
            addedge(a,b,1);
            addedge(b,a,-1);
        }
    }
    
    void spfa(int u) {
        inque[u]=1;
        l=min(l,c[u]);
        r=max(r,c[u]);
        for(int i=g[u];~i;i=next[i]) if(!inque[v[i]]) {
            c[v[i]]=c[u]+dist[i];
            spfa(v[i]);
        }
    }
    
    void solve() {
        for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,0,0);
        if(ans&&ans<=2) {
            printf("-1 -1
    ");
            return;    
        }
        if(ans) {
            maxres=ans;
            for(int i=3;i<=maxres;i++) if(maxres%i==0) {
                minres=i;
                break;
            }
        }
        else for(int i=1;i<=n;i++) if(!inque[i]) {
            l=r=c[i]=0;
            spfa(i);
            maxres+=r-l+1;
            minres=3;
        }
        if(maxres<3) maxres=minres=-1;
        printf("%d %d
    ",maxres,minres);
    }
    
    int main() {
        build();
        solve();
        return 0;
    }
  • 相关阅读:
    ***25 k个一组反转链表
    24 交换链表中相连的节点
    19 删除链表倒数第N个节点
    2 两数相加
    23 合并K个有序链表
    21 合并两个有序链表
    114 判断一个链表是否存在环并返回环起点
    141 链表是否存在环
    160 寻找链表交点
    92 指定区间链表逆置
  • 原文地址:https://www.cnblogs.com/invoid/p/5609253.html
Copyright © 2020-2023  润新知