bzoj 1064 假面舞会 图论??+dfs

有两种情况需要考虑

1.链:可以发现对最终的k没有影响

2.环:如果是真环(即1->2->3->4->1),可以看出所有可行解一定是该环的因数

 假环呢??(1->2->3->4,1->5->4),可行解便是两条路的差值的因数

So??对于每条边,正建1,反建-1,dfs,每出一个环,就计算gcd

没有环呢??最小是3,最大是所有链加和喽

#include<cstdio>
#include<iostream>
#include<cstring>
#define N 100005
using namespace std;
int Gcd,n,m,e=1,head[N],dep[N],maxn,minn,len;
bool flag[N];
struct edge{
    int v,w,next;
}ed[2000500];
int gcd(int x,int y){
    return y==0?x:gcd(y,x%y);
}
int abs(int x){
    return x>0?x:-x;
}
void add(int u,int v,int w){
    ed[e].v=v; ed[e].w=w;
    ed[e].next=head[u];
    head[u]=e++;
}
void dfs(int x,int k){
    flag[x]=1; dep[x]=k;
    maxn=max(maxn,k);
    minn=min(minn,k);
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v,w=ed[i].w;
        if(!flag[v]) dfs(v,k+w);
        else  Gcd=gcd(Gcd,abs(dep[v]-k-w));
    }
}
int main()
{
    int u,v;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        add(u,v,1); add(v,u,-1);
    }
    for(int i=1;i<=n;i++){
        if(!flag[i]){
            maxn=-0x7fffffff;
            minn=0x7fffffff;
            dfs(i,1);
            len+=maxn-minn+1;
        }
    }
    if(Gcd==0){
        if(len<3) printf("-1 -1");
        else printf("%d 3\n",len);
    }
    else{
        if(Gcd<3) printf("-1 -1");
        else{
            int i;
            for(i=3;i<=Gcd&&Gcd%i!=0;i++){}
            printf("%d %d\n",Gcd,i);
        }
    }
    return 0;
}


转载于:https://www.cnblogs.com/Ren-Ivan/p/7746759.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值