BZOJ 4116[WorldFinal2015]Tours

题面:

4116: [Wf2015]Tours

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 129  Solved: 46
[Submit][Status][Discuss]

Description

给定一张n个点m条边的无向图,你需要选择一个颜色种类数k,然后用这k种颜色给每条边染色,要求对于图中任意一个简单环,每种颜色的边的数量都相同,求所有可行的k

Input

第一行两个正整数n,m
接下来m行,每行两个正整数x,y(1<=x<y<=n),代表一条无向边
数据保证无重边无自环

Output

一行输出所有可行的k,按递增顺序输出 6 6 1 2 2 3 1 3 1 4 2 5 3 6

Sample Input

6 6
1 2
2 3
1 3
1 4
2 5
3 6

Sample Output

1 3

HINT

 n,m<=2000

 

我们先将边集分为若干个子集,满足每个简单环都可以有这些子集相加得到,答案就是这些子集大小$gcd$的约数。

对于一个简单环,它上面的边一定不是桥边,而且不在其他简单环上,所以我们枚举每一条桥边,把它删去,之后统计变成桥边的边的个数。

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 using namespace std;
  6 #define maxn 2010
  7 struct edge
  8 {
  9     int u,v,id,nex;
 10 }e[maxn<<1];
 11 int pr[maxn],cnt=1;
 12 int from[maxn],to[maxn];
 13 inline void add(int u,int v,int w)
 14 {
 15     e[++cnt]=(edge){u,v,w,pr[u]};
 16     pr[u]=cnt;
 17     e[++cnt]=(edge){v,u,w,pr[v]};
 18     pr[v]=cnt;
 19 }
 20 inline int read()
 21 {
 22     int s=0,f=1;
 23     char ch=getchar();
 24     while(ch<'0'||ch>'9')
 25     {
 26         if(ch=='-')
 27             f=-1;
 28         ch=getchar();
 29     }
 30     while(ch>='0'&&ch<='9')
 31         s=s*10+ch-'0',ch=getchar();
 32     return s*f;
 33 }
 34 int low[maxn],dfn[maxn];
 35 int scc_dfn;
 36 bool bridge[maxn],vis[maxn],rem[maxn];
 37 void tarjan(int u,int E)
 38 {
 39     low[u]=dfn[u]=++scc_dfn;
 40     for(int i=pr[u];i;i=e[i].nex)
 41     {
 42         if(i^E^1)
 43         {
 44             int v=e[i].v;
 45             if(dfn[v])
 46                 low[u]=min(low[u],dfn[v]);
 47             else
 48             {
 49                 tarjan(v,i);
 50                 low[u]=min(low[u],low[v]);
 51                 if(low[v]>dfn[u])
 52                     bridge[e[i].id]=true;
 53             }
 54         }
 55     }
 56 }
 57 inline void init()
 58 {
 59     scc_dfn=0;cnt=1;
 60     memset(pr,0,sizeof(pr));
 61     memset(low,0,sizeof(low));
 62     memset(dfn,0,sizeof(dfn));
 63     memset(bridge,0,sizeof(bridge));
 64 }
 65 int n,m;
 66 int main()
 67 {
 68     n=read();
 69     m=read();
 70     int u,v;
 71     for(int i=1;i<=m;i++)
 72     {
 73         from[i]=read();
 74         to[i]=read();
 75         add(from[i],to[i],i);
 76     }
 77     for(int i=1;i<=n;i++)
 78         if(!dfn[i])
 79             tarjan(i,0);
 80     memcpy(rem,bridge,sizeof(bridge));
 81     int ans=0;
 82     for(int i=1;i<=m;i++)
 83     {
 84         int tot=1;
 85         if(rem[i]||vis[i])
 86             continue;
 87         init();
 88         for(int j=1;j<=m;j++)
 89             if(j!=i)
 90                 add(from[j],to[j],j);
 91         for(int i=1;i<=n;i++)
 92             if(!dfn[i])
 93                 tarjan(i,0);
 94         for(int j=1;j<=m;j++)
 95             if(!rem[j]&&bridge[j])
 96                 vis[j]=true,++tot;
 97         ans=__gcd(ans,tot);
 98     }
 99     for(int i=1;i<=ans;i++)
100         if(ans%i==0)
101         {
102             printf("%d",i);
103             if(i!=ans)
104                 putchar(' ');
105         }
106 }
BZOJ 4116

 

posted @ 2017-09-24 21:24  avancent  阅读(260)  评论(0编辑  收藏  举报