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

时间: 2024-10-12 16:19:57

BZOJ 4116[WorldFinal2015]Tours的相关文章

BZOJ 4116 Wf2015 Tours Tarjan

题目大意:给定一张n个点m条边的无向图,你需要选择一个颜色种类数k,然后用这k种颜色给每条边染色,要求对于图中任意一个简单环,每种颜色的边的数量都相同,求所有可行的k 考虑将边集E拆成一些子集{E1,E2,E3,..},满足任意一个简单环可以被拆成一些子集的和,且不存在两个子集合并后仍满足条件,那么答案就是gcd{|E1|,|E2|,|E3|,..}的所有约数 那么如何确定这些子集呢? "尝试删掉每一条非桥边并统计有多少边成为了新的桥边.得到的数+1的gcd."--Petr Touri

【BZOJ】初级水题列表——献给那些想要进军BZOJ的OIers(自用,怕荒废了最后的六月考试月,刷刷水题,水水更健康)

BZOJ初级水题列表——献给那些想要进军BZOJ的OIers 代码长度解释一切! 注:以下代码描述均为C++ RunID User Problem Result Memory Time Code_Length 695765 Eolv 1000 Accepted 804 kb 0 ms 118 B 739478 Eolv 2463 Accepted 804 kb 0 ms 134 B 696662 Eolv 1968 Accepted 1272 kb 48 ms 137 B 739546 Eolv

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)

012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列

【BZOJ】【1016】【JSOI2008】最小生成树计数

Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的,再加上权值为2和2的,不也满足题意吗?事实上,如果这样的话……最小生成树应该是1和2,而不是1和3或2和2!!! 所以呢?所以对于一个图来说,最小生成树有几条边权为多少的边,都是固定的!所以我们可以做一遍Kruskal找出这些边权,以及每种边权出现的次数.然后,对于每种边权,比方说出现了$v_i$

【BZOJ】【2844】albus就是要第一个出场

高斯消元解XOR方程组 srO  ZYF  Orz 膜拜ZYF…… http://www.cnblogs.com/zyfzyf/p/4232100.html 1 /************************************************************** 2 Problem: 2844 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:252 ms 7 Memory:2052 kb 8 *******