LGOJ P1197 [JSOI2008]星球大战
Posted #include
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LGOJ P1197 [JSOI2008]星球大战相关的知识,希望对你有一定的参考价值。
我十分喜欢自带大常数的STL
思路都是反着来,先把该删的节点都删除,再一个一个往图里面加。
加节点的时候分类讨论:
假设当前要加的节点是 u ,用
set<int> S;
来存储 u 节点直接连接的点 v 的所属集合的值 find(v) ,这样 S.size() 的值就表示 u 节点究竟链接了几种不同的联通块。再分类讨论:
if (S.size() == 0)tpc++;//若这是一个单独的点
//添加之后tpc++
else if (S.size() == 1);//若这个点只连接了一个联通块
//那么她的存在就没有什么所谓
else
{
tpc -= S.size(); //如果这个点连接了两个以上的块
//那么显然tpc要减去(S.size()-1)
tpc++;
}
注:tpc == type_count.
剩下的事情就简单了,先dfs一次求末状态的块数量,链表存贮 k 次操作,倒着加点,再倒着输出即可。
// P1197.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
char c = getchar();
int x = 0;
bool minus = 0;
for (; !isdigit(c); c = getchar())
if (c == '-')minus = 1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
if (minus)return -x;
return x;
}
const int M = 200005, N = 400005;
int n, m, k, f[N], tpc;
vector<int> G[N];//Graph
list<int> atk;//attack_list
bool ban[N];//值为1表示当前节点不可用
bool vis[N];//dfs用的数组
list<int>asl;//answer_list
set<int>S;
//普通的并查集
inline int find(int x)
{
if (f[x] == x)return x;
return f[x] = find(f[x]);
}
inline void unity(int x, int y)
{
int u = find(x);
int v = find(y);
f[f[u]] = v;
}
//普通的dfs
void dfs(int u)
{
int v = 9999;
vis[u] = 1;
for (int i = 0; i < G[u].size(); i++)
{
v = G[u][i];
if (!ban[v] && !vis[v])
{
unity(u, v);
dfs(v);
}
}
}
//核心代码↓
inline void work()
{
asl.push_front(tpc);//最后的情况放链表首
for (list<int>::iterator it = atk.begin(); it != atk.end(); it++)
{
//欲添加的节点为u,u直接连接的节点为v
int u = *it;
S.clear();
ban[u] = 0;
for (int j = 0; j < G[u].size(); j++)
{
int v = G[u][j];
if (ban[v])continue;
// ↑ v在之前被删除,不能选
S.insert(find(v));
unity(u, v);
}
if (S.size() == 0)tpc++;
else if (S.size() == 1);
else
{
tpc -= S.size();
tpc++;
}
//tpc放asl首
asl.push_front(tpc);
}
}
int main()
{
cin >> n >> m;
int u = 0, v = 0;
for (int i = 1; i <= m; i++)
{
u = read();
v = read();
G[u].push_back(v);
G[v].push_back(u);
}
k = read();
int t = 0;
for (int i = 1; i <= k; i++)
{
t = read();
ban[t] = 1;
atk.push_front(t);
}
for (int i = 0; i < n; i++)f[i] = i;
for (int i = 0; i < n; i++)
{
if (!vis[i] && !ban[i])
{
tpc++;
dfs(i);
}
}
work();
for (list<int>::iterator it = asl.begin(); it != asl.end(); it++)
printf("%d
", *it);
return 0;
}
以上是关于LGOJ P1197 [JSOI2008]星球大战的主要内容,如果未能解决你的问题,请参考以下文章