zoukankan      html  css  js  c++  java
  • [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 6

    OUTPUT

    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 }
    View Code
  • 相关阅读:
    win 程序开机自启动设置
    火柴:电脑效率工具
    全新思维导图 XMind ZEN v10.0.0 中文破解版
    Linux 上 10 个最好的 Markdown 编辑器
    iobit-unlocker --- 类似 Unlocker 工具,强制删除文件或文件夹
    EV录屏 --- 免费无水印,集视频录制与直播功能于一身的桌面录屏软件, 支持录屏涂鸦、实时按键显示、视频体积压缩等实用功能
    办公书籍推荐
    喝水计算器
    Linux find命令忽略目录的查找方法
    重装系统之前需要做的checklist
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7780576.html
Copyright © 2011-2022 走看看