dfs计算途中所有联通块的数量,并计算其中是否有特殊点(炸弹)。
炸鸡最近在 ɔiq平台上白嫖了一款游戏:《炸蛋人》。
《炸蛋人》的主角炸蛋人生活在一张n个结点(编号1到m条边的无向图上(图不一定联通),炸鸡可以控制炸蛋人进行两种操作:移动和放置炸蛋。具体说明如下。
移动:炸蛋人可以移动到当前所在结点通过一条边相连的相邻节点,但炸蛋人只能移动到没有炸蛋的结点。注意,尽管不能移动到有炸蛋的结点,但允许炸蛋人从一个当前有炸蛋的结点出发,移动到相邻没有炸蛋的结点。
放置炸蛋:炸蛋人在当前位置放置一枚炸蛋,炸蛋一经放置就会永久存在于图中(炸蛋全称为炸制金黄色的农家土鸡蛋,因此当然不会爆炸),每个位置可以放置多枚炸蛋。已知炸蛋人所在的无向图初始没有炸蛋,炸蛋人出现在了地图上的S点,炸鸡对炸蛋人进行了一系列的操作,炸蛋人最终停留在了T点。现在,给出无向图最终的情况,请你求出有多少种可能的起点终点方案(S,T),两种方案不同当且仅当它们的起点和终点至少有一个不同。若无合法方案输出0。
计算有炸弹的连通块的数量。在一个连通块内不论炸弹怎样分布,都可以达到目的。
若数量为0,直接sizisizisizjsizj;若为1,输出有炸弹连通块内的sizsiz。
dfs时,要先对dfs传入的点进行标记,然后在dfs,不然可能会漏点
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
vector<int> g[100010];
bool st[100010];
int have_bomb,c[100010];
int n, m,sz;
void dfs(int u)
{
if(c[u])
have_bomb = 1;
st[u] = true;
sz++;
for(auto a:g[u])
if(!st[a]) dfs(a);
}
int main()
{
cin>>n>>m;
int u, v;
for (int i = 0; i < m;i++)
{
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= n;i++) scanf("%d", &c[i]);
int bomb = 0,last_bomb=0;
vector<ll> p_size;
for (int i = 1; i <= n;i++)
{
if(!st[i])
{
sz=have_bomb = 0;
dfs(i);
bomb += have_bomb;
p_size.push_back(sz);
if(have_bomb) last_bomb = p_size.size()-1;
}
}
if(bomb==0)
{
ll ans=0;
for(auto a:p_size) ans+=(a*a);
printf("%lld", ans);
}
else if(bomb==1) printf("%lld", (ll)p_size[last_bomb] * p_size[last_bomb]);
else printf("%d", 0);
return 0;
}
浙公网安备 33010602011771号