当前位置:网站首页>Forest Program dfs+tanjar仙人掌
Forest Program dfs+tanjar仙人掌
2022-08-09 07:01:00 【swust_fang】
题目链接 CCPC2019 F题。
题意:给一颗仙人掌树,让你求每一个小环的边的个数,用快速幂即可求解。
思路:第一反应是tanjar乱搞,把每个环上的点取出来,类似于缩点的方法。但是忽然感觉dfs能做,因为仙人掌比较特殊的性质,就是一个环上不会有多个分支。
那么首先我们从任一点出发,dfs下去记录深度并且标记,当我们到达一个点标记过且深度小于当前点,证明我们刚好走了一个环,那么两点的深度差+1就是该环的边数,如果碰到标记过深度比当前点深度大呢,其实这个就是我们之前已经处理过的环了,直接跳过不管就行,就这样就完了。
dfs代码:
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
typedef unsigned long long ull;
typedef long long ll;
#define pii make_pair
#define pr pair<int,int>
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
const int mod=998244353;
const int maxn=3e5+5;
const int maxm=1e6+5;
struct node
{
int to,p;
}edge[maxm];
int head[maxn],sign;
int vis[maxn];
int n,m;
ll res;
ll qmod(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll qqmod(ll a,ll b)
{
ll ans=qmod(a,b);
ans=(ans-1+mod)%mod;
return ans;
}
void init()
{
for(int i=0;i<=n;i++) head[i]=-1,vis[i]=0;
sign=0;
}
void add(int u,int v)
{
edge[sign]=node{v,head[u]};
head[u]=sign++;
}
void dfs(int u,int cnt)
{
vis[u]=cnt;
for(int i=head[u];~i;i=edge[i].p)
{
int v=edge[i].to;
if(vis[v])
{
if(vis[u]-vis[v]>1)//判断是不是走了父亲节点
{
ll c=vis[u]-vis[v]+1;
res=res*qqmod(2,c)%mod;
m-=c;
}
}
else dfs(v,cnt+1);
}
}
int main()
{
int x,y;
while(scanf("%d %d",&n,&m)!=EOF)
{
if(m==0)
{
puts("0");
continue;
}
init();
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
add(x,y),add(y,x);
}
res=1;
dfs(1,1);
res=res*qmod(2,m)%mod;
printf("%lld\n",res);
}
return 0;
}
然后就是tanjar的做法。
其实很多人用点双做这道题我觉得没必要,而且我写的一直超时(-.-
问题在于tanjar求联通分量其实是求大环,就是第二个样例其实就是一个大的连通分量
但是大概思路都是一样的,也当是复习一哈。
当我们tanjar到一个点low[v]>=low[u]证明u点是一个割点,我们缩点的方法是把stack中直到等于u的点全部取出来
这里就是直到等于v的点全部取出来就行,然后+1就是该块(块描述应该是没问题)的数量求出来了,
只有块数量大于2才算一个环
代码是T的,不晓得为啥~(希望大佬能帮助一下!
//#pragma comment (linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
typedef unsigned long long ull;
typedef long long ll;
#define pii make_pair
#define pr pair<int,int>
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
const int mod=998244353;
const int maxn=3e5+5;
const int maxm=1e6+5;
struct node
{
int to,p;
}edge[maxm];
int head[maxn],sign;
int n,m;
int Stack[maxn],low[maxn],dfn[maxn];
int num[maxn];
int top,t,cnt;
ll p[maxn],r[maxn];
ll res;
ll qmod(ll a,ll b)
{
if(r[b]) return r[b];
int c=b;
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return r[c]=ans;
}
ll qqmod(ll a,ll b)
{
if(p[b]) return p[b];
ll ans=qmod(a,b);
ans=(ans-1+mod)%mod;
return p[b]=ans;
}
void init()
{
t=top=cnt=sign=0;
for(int i=1;i<=n;i++)
{
low[i]=dfn[i]=0;
head[i]=-1;
}
}
void add(int u,int v)
{
edge[sign]=node{v,head[u]};
head[u]=sign++;
}
void tanjar(int u,int pre)
{
dfn[u]=low[u]=++t;
Stack[++top]=u;
for(int i=head[u];~i;i=edge[i].p)
{
int v=edge[i].to;
if(v==pre) continue;
if(!dfn[v])
{
tanjar(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
cnt++;
num[cnt]=0;
int x;
do{
x=Stack[top--];
num[cnt]++;
}while(x!=v);
num[cnt]++;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
if(m==0) {puts("0");continue;}
init();
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
add(x,y),add(y,x);
}
res=1;
for(int i=1;i<=n;i++)
if(!dfn[i]) tanjar(i,i);
for(int i=1;i<=cnt;i++)
if(num[cnt]>=3) res=res*qqmod(2,num[cnt])%mod,m-=num[cnt];
res=res*qmod(2,m)%mod;
printf("%lld\n",res);
}
}
边栏推荐
- install flask
- MySQL高级特性之分布式(XA)事务的介绍
- shardingsphere data sharding configuration item description and example
- C语言的内置宏(定义日志宏)
- 2022-08-08: Given an array arr, it represents the height of the missiles that will appear in order from morning to night.When the cannon shoots missiles, once the cannon is set to shoot at a certain h
- Zero shift of leetcode
- Distributed id generator implementation
- 线程池总结
- 【MySQL】update mysql.user set authentication_string=password(“123456“) where User=‘root‘; 报错
- list与string转换
猜你喜欢
longest substring without repeating characters
Search 1688 product interface by image (item_search_img-search 1688 product by image (Politao interface) code docking tutorial
2022-08-08: Given an array arr, it represents the height of the missiles that will appear in order from morning to night.When the cannon shoots missiles, once the cannon is set to shoot at a certain h
【报错】Root Cause com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
Inception V3 Eye Closure Detection
The working principle of the transformer (illustration, schematic explanation, understand at a glance)
Zero shift of leetcode
半导体新能源智能装备整机软件系统方案设计
学习小笔记---机器学习
db.sqlite3 has no "as Data Source" workaround
随机推荐
排序第一节——插入排序(直接插入排序+希尔排序)(视频讲解26分钟)
Service
AD画PCB板教程 20分钟讲清楚操作流程 铺铜 网络标号
db.sqlite3 has no "as Data Source" workaround
jvm线程状态
Transaction concluded
imageio读取.exr报错 ValueError: Could not find a backend to open `xxx.exr‘ with iomode `r`
什么是分布式事务
日期处理,字符串日期格式转换
SSL证书最长有效期13个月,还有必要一次申请多年吗?
XILINX K7 FPGA+RK3399 PCIE驱动调试
找不到和chrome浏览器版本不同的chromedriver的解决方法
P7 Alibaba Interview Questions 2020.07 Sliding Window Algorithm (Alibaba Cloud Interview)
我入职阿里后,才知道原来简历这么写
P6 ali machine test of 2020 Fibonacci number
(本章节完结)排序第五节——非比较排序(计数排序+基数排序+桶排序)(附有自己的视频讲解)
car-price-deeplearning-0411
RK3568商显版开源鸿蒙板卡产品解决方案
学习小笔记---机器学习
MySQL高级特性之分布式(XA)事务的介绍