2019 CCPC秦皇岛 F Forest Program

关键在于怎样找到各个环及其边数。

  1. dfs搜
  2. 双连通分量
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef pair<int,int> piir;
 4 typedef long long ll;
 5 const int maxn = 3e5+5;
 6 const int maxm = 5e5+5;
 7 const int INF  = 0x3f3f3f3f;
 8 const int mod  = 998244353;
 9
10 int n,m,vis[maxn],dfn[maxn];
11 ll ans,sum;
12
13 struct edge{
14     int v,next;
15 }e[maxm*2];
16 int head[maxn],tot;
17 void init(){
18     memset(head,-1,sizeof(head));tot=0;
19     ans=1;
20     sum=0;
21     memset(vis,0,sizeof(vis));
22     memset(dfn,0,sizeof(dfn));
23 }
24 void add(int u,int v){
25     e[tot].v=v;
26     e[tot].next=head[u];
27     head[u]=tot++;
28 }
29
30 ll qpow(ll base,ll n) {
31     ll ans = 1;
32     while (n) {
33         if (n & 1) ans = (ans % mod) * (base % mod) % mod;
34         base = (base % mod) * (base % mod) % mod;
35         n >>= 1;
36     }
37     return ans % mod;
38 }
39 void dfs(int u,int fa,int stp){
40     //printf("u:%d fa:%d stp%d\n",u,fa,stp);
41
42     vis[u]=1;dfn[u]=stp;
43     for(int i=head[u];i!=-1;i=e[i].next){
44         int v=e[i].v;
45         if(v==fa || vis[v]==2) continue;
46         if(vis[v]==1){// find circle
47             sum += (stp-dfn[v]+1);
48             //printf("u%d v%d stp%d dfnv%d\n",u,v,stp,dfn[v]);
49             ans = (ans*(qpow(2,stp-dfn[v]+1)-1))%mod;
50             //printf("ans:%d\n",ans);
51             continue;
52         }
53         dfs(v,u,stp+1);
54     }
55     vis[u]=2;
56 }
57 int main(){
58     //freopen("in.txt","r",stdin);
59     while(scanf("%d%d",&n,&m)!=EOF){
60         init();
61         for(int u,v,i=1;i<=m;i++){
62             scanf("%d%d",&u,&v);
63             add(u,v),add(v,u);
64         }
65         for(int i=1;i<=n;i++){
66             if(vis[i]==0) {
67                 dfs(i,-1,0);
68             }
69         }
70         ans = (ans*qpow(2,m-sum))%mod;
71         printf("%lld\n",ans);
72     }
73     return 0;
74 }

原文地址:https://www.cnblogs.com/ordinarv/p/11778325.html

时间: 2024-11-09 23:38:16

2019 CCPC秦皇岛 F Forest Program的相关文章

[CCPC2019秦皇岛] F. Forest Program

[CCPC2019秦皇岛 F] Link https://codeforces.com/gym/102361/problem/F Description 给定一个仙人掌,删去一些边可以让它变成一个森林(一棵树也是森林),求方案数. \(n \le 300000, m \le 500000\) Solution 用 DFS 暴力找环,然后乘法原理算一下即可.注意非环边也会有贡献. DFS 可以模仿 Tarjan 算法写. Code #include <bits/stdc++.h> using n

Forest Program(2019ccpc秦皇岛F)

题:http://acm.hdu.edu.cn/showproblem.php?pid=6736 题意:删掉一些边使得图不存在点双,求方案数. 分析:若一条边不属于点双,那么这条边有删和不删俩种选择,若找到点双,点双中必须删掉一条边(题目有保证一条边只能属于一个点双,所以不用担心一条边用于多个点双)tarjan找点双,若为点双则必须删掉点双中的一条边 #include<bits/stdc++.h> using namespace std; typedef long long ll; #defi

三个倒霉鬼的CCPC秦皇岛打铁记

出发: 2019年9月20日凌晨四点,我和Dicer还有凯凯踏上了前往秦皇岛的火车,一趟神奇的旅途就这样开始了... 第一次坐那么久的火车,虽然是硬卧,但是有些难受,由于空调吹冷风,结果,我感冒了.. 到了宾馆已经晚上十点半了,又饿又困,然后晚上点了40+的外卖,实不相瞒,没有学校的正新鸡排好吃多了.洗了个热水澡就睡觉了. 报道 宾馆和东大秦皇带分校离得很近,步行了20分钟就到了,报道完就在食堂摸鱼...午饭吃的也挺淡的,忘了说一句我袋子又又又忘了拿了(心累). 热身赛 我觉得热身赛就表明了这场

2019 CCPC网络赛

一到网络赛,大家都是东亚之光 1001 00:23:46 solved by hl 签到 枚举一下位就行了 #include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset

2019 CCPC 网络选拔 Kth-occurrence

题意 给出一个字符串,每次询问其一个子串\([S_l,S_r]\)在原串中第\(k\)次出现所在的位置(开头位置) 解法 题意很简洁,思路也很简洁 就是代码巨难打 总之这道题还是让我很大程度上加深了对于\(SAM\)的认识啦,还去学了一下线段树合并 首先,根据后缀自动机的性质我们能知道题目所要求的的实际上是 \([S_l,S_r]\)所代表串所在后缀自动机的结点\(endpos\)集合中的第\(k\)个数 求区间第\(k\)大?权值线段树上啦 我们知道,对于后缀自动机上的某个结点,其\(endp

2019 MIST IUPC F - Palindromadness

题解:等我知道为什么了再写.反正是个我觉得很难的回文自动机的题. #include<bits/stdc++.h> #define ls (x<<1) #define rs (x<<1|1) #define ll long long #define pb push_back #define mp make_pair #define db double #define pii pair<int,int> using namespace std; const in

ccpc秦皇岛部分题解

A. 题意:就是有一个大桌子,环绕有顺势站1~m共m个座位,n个选手坐在部分位置上.然后如果有一个人a了一道题,却没有立刻发气球给他,他产生怒气值是发气球给他的时间减去a题时间.现在有一个机器人顺时针环绕桌子发球,每个单位时间走过一个位置.问机器人在哪个位置开始发气球总怒气值最小,输出最小怒气值. 其实是个傻逼思维题.假如他从位置m开始发气球,对于每个位置i,他到达的时间为k*m+i,所以对于每个它在时刻t a的题,他需要等待t-k*m+i中最小的正整数时间.随便算算就能知道每一题从m位置开始具

2019 CCPC 网络赛第三题 K-th occurrence 后缀数组+划分树+ST表+二分

题意:给你一个长度为n的字符串,每次询问给出三个数:L , R , K,表示原串 L 到 R 的子串在原串第K次出现的首字母的位置 解题思路:对子串的大量操作,不难想到后缀数组(后缀树/后缀自动机不会,所以没想到),注意到子串s[L.....R]必然是某一个后缀的前缀,所以所有前缀是该子串的后缀的排名(即rank数组的值)必定连续,也就是说在后缀数组(sa数组)中,下标是连续的,那么就是求区间第K大了(因为sa数组的值代表的是在字符串中的位置)(这里区间第K大我用划分树求),至于这一段区间的起点

2019 CCPC - 网络选拔赛 D path(求第k短路)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6705 题目大意:给出n个点,m条边,q个询问,每个询问回答第$k_{i}$短路 解题报告:使用STL中的multiset,好处是头结点和尾结点都方便删除,记录每个以i结束的边的权值,然后再进行扩展,当mulitiset中的size大于询问中最大的k时,将尾部的点给删掉,还有个剪枝就是一开始建图的时候按权值降序建图,这样用链式前向星遍历的时候,边的顺序就是升序的,在bfs增广的时候可以剪枝,详细见代码