zoukankan      html  css  js  c++  java
  • 【NOI2008T1】假面舞会-DFS环处理+最大公因数

    测试地址:假面舞会

    做法:这题看上去就是找环然后求最大公因数,然后下一步就不会做了,看了题解就跪了......主要这个处理方法太神奇了。

    首先建图肯定不能按照原来的图建,因为需要枚举起点来走,会TLE,所以我们对于原图a->b这条边,连一条a->b边权为1,再连一条b->a边权为-1。如果图中有非零环,那么最大的答案就是所有非零环长的最大公因数,最小答案就是所有非零环长的最小的大于2的公因数。如果图中没有非零环,就统计每个连通块的最长链长,这个长度加上1就是这个连通块的最大答案,累加每个连通块的最大答案就是整体的最大答案,最小答案就是3。如果最大答案小于3则无解。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define inf 1000000000
    using namespace std;
    int n,m,cnt[100010],first[100010]={0},tot=0,maxn,minn;
    int len[100010]={0},ans1,ans2;
    struct edge {int v,d,next;} e[2000010];
    bool vis[100010]={0},flag=0;
    
    int gcd(int a,int b)
    {
      return b!=0?gcd(b,a%b):a;
    }
    
    void insert(int a,int b,int d)
    {
      e[++tot].v=b,e[tot].d=d,e[tot].next=first[a],first[a]=tot;
    }
    
    void dfs(int v)
    {
      vis[v]=1;
      maxn=max(maxn,cnt[v]);
      minn=min(minn,cnt[v]);
      for(int i=first[v];i;i=e[i].next)
      {
        if (!vis[e[i].v])
    	{
    	  cnt[e[i].v]=cnt[v]+e[i].d;
    	  dfs(e[i].v);
    	}
        else if (cnt[v]+e[i].d-cnt[e[i].v]!=0)
    	{
    	  flag=1;
    	  if (ans1==0) ans1=abs(cnt[v]+e[i].d-cnt[e[i].v]);
    	  else ans1=gcd(ans1,abs(cnt[v]+e[i].d-cnt[e[i].v]));
    	}
      }
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      for(int i=1,a,b;i<=m;i++)
      {
        scanf("%d%d",&a,&b);
    	insert(a,b,1),insert(b,a,-1);
      }
      
      ans1=0;
      for(int i=1;i<=n;i++)
      if (!vis[i])
      {
        cnt[i]=0;
    	maxn=-inf,minn=inf;
    	dfs(i);
    	if (!flag) ans1+=maxn-minn+1;
      }
      
      ans1=abs(ans1);
      if (ans1<3) ans1=-1,ans2=-1;
      else if (!flag) ans2=3;
      else
      {
        for(int i=3;i<=ans1;i++)
    	  if (ans1%i==0) {ans2=i;break;}
      }
      
      printf("%d %d",ans1,ans2);
      
      return 0;
    }
    


  • 相关阅读:
    HDU 4539郑厂长系列故事――排兵布阵(状压DP)
    HDU 2196Computer(树形DP)
    HDU 4284Travel(状压DP)
    HDU 1520Anniversary party(树型DP)
    HDU 3920Clear All of Them I(状压DP)
    HDU 3853LOOPS(简单概率DP)
    UVA 11983 Weird Advertisement(线段树求矩形并的面积)
    POJ 2886Who Gets the Most Candies?(线段树)
    POJ 2828Buy Tickets
    HDU 1394Minimum Inversion Number(线段树)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793753.html
Copyright © 2011-2022 走看看