[Wf2015]Tours
[Wf2015]Tours
题目
给定一张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 6OUTPUT
1 3
解题报告
其实这道题的关键在于找到每个简单环的边数,所以我们考虑如何处理简单环
显然,在一个简单环中,删去一条边,剩下的边就会变为割边
所以就可以得出做法:枚举原图非桥边,删去该边,处理出新增的桥边数量,所有数量+1的$GCD$所有的因数即为答案
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 inline int read(){ 6 int sum(0);char ch(getchar()); 7 for(;ch<'0'||ch>'9';ch=getchar()); 8 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 9 return sum; 10 } 11 int n,m,tot,ans(-1); 12 int dfn[2005],low[2005],cnt,tmp; 13 int fro[2005],to[2005]; 14 bool bridge[2005],vis[2005]; 15 struct edge{ 16 int e,id; 17 edge *n; 18 }*pre[2005],a[4005]; 19 inline void insert(int s,int e,int id){ 20 a[++tot].e=e; 21 a[tot].id=id; 22 a[tot].n=pre[s]; 23 pre[s]=&a[tot]; 24 } 25 inline void init(){ 26 memset(pre,NULL,sizeof(pre)); 27 memset(dfn,0,sizeof(dfn)); 28 memset(low,0,sizeof(low)); 29 tot=cnt=tmp=0; 30 } 31 inline void tarjan(int u,int fa){ 32 dfn[u]=low[u]=++cnt; 33 for(edge *i=pre[u];i;i=i->n){ 34 int e(i->e);if(e==fa)continue; 35 if(!dfn[e]){ 36 tarjan(e,u); 37 low[u]=min(low[u],low[e]); 38 if(low[e]>dfn[u])bridge[i->id]=1; 39 } 40 else low[u]=min(low[u],dfn[e]); 41 } 42 } 43 inline void dfs(int u,int fa){ 44 dfn[u]=low[u]=++cnt; 45 for(edge *i=pre[u];i;i=i->n){ 46 int e(i->e);if(e==fa)continue; 47 if(!dfn[e]){ 48 dfs(e,u); 49 low[u]=min(low[u],low[e]); 50 if(low[e]>dfn[u]&&bridge[i->id]==0)++tmp,vis[i->id]=1; 51 } 52 else low[u]=min(low[u],dfn[e]); 53 } 54 } 55 inline int gcd(int x,int y){ 56 return x%y?gcd(y,x%y):y; 57 } 58 int main(){ 59 n=read();m=read(); 60 for(int i=1;i<=m;++i){ 61 int x(read()),y(read()); 62 fro[i]=x;to[i]=y; 63 insert(x,y,i);insert(y,x,i); 64 } 65 for(int i=1;i<=n;++i) 66 if(!dfn[i]) 67 tarjan(i,0); 68 for(int i=1;i<=m;++i){ 69 if(bridge[i]||vis[i])continue; 70 init(); 71 // for(int j=1;j<=m;++j)cout<<j<<' '<<bridge[j]<<endl;cout<<endl;//cout<<"ban "<<i<<endl; 72 for(int j=1;j<=m;++j) 73 if(j^i){//cout<<j<<' '<<fro[j]<<' '<<to[j]<<endl; 74 insert(fro[j],to[j],j); 75 insert(to[j],fro[j],j); 76 } 77 for(int j=1;j<=n;++j) 78 if(!dfn[j]) 79 dfs(j,0); 80 // for(int j=1;j<=m;++j)cout<<j<<' '<<bridge[j]<<endl;cout<<endl; 81 if(ans==-1)ans=tmp+1; 82 else ans=gcd(ans,tmp+1); 83 // cout<<tmp<<' '<<ans<<endl; 84 } 85 // cout<<ans<<endl; 86 for(int i=1;i<=ans;++i) 87 if(ans%i==0){ 88 printf("%d",i); 89 if(i^ans)putchar(' '); 90 } 91 }